mirror of
https://github.com/luxfi/mpc.git
synced 2026-09-24 00:26:24 +00:00
Consolidate the hanzoai/mpc repo into luxfi/mpc (the canonical, deployed MPC — v1.16.0, running as ghcr.io/luxfi/mpc across all clusters). hanzoai/mpc (legacy v1.0.6) carried 5 chain-specific threshold-signing examples luxfi/mpc lacked; they already import github.com/luxfi/mpc/pkg/threshold, so this is a clean port. hanzoai/mpc is being archived — nothing imports it and the deployments already run luxfi/mpc.
195 lines
6.0 KiB
Go
195 lines
6.0 KiB
Go
// Copyright (c) 2024-2025 Hanzo AI Inc.
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
// Solana Threshold Signing Example
|
|
// Demonstrates threshold EdDSA signing for Solana
|
|
package main
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"log"
|
|
|
|
"github.com/luxfi/mpc/pkg/threshold"
|
|
)
|
|
|
|
func main() {
|
|
fmt.Println("=== Solana Threshold Signing Example ===")
|
|
fmt.Println()
|
|
|
|
// Create unified threshold API
|
|
api := threshold.NewUnifiedThresholdAPI()
|
|
defer api.Close()
|
|
|
|
// Define MPC nodes with 2-of-3 threshold
|
|
partyIDs := []string{"validator1", "validator2", "validator3"}
|
|
thresholdValue := 1 // 2-of-3 threshold
|
|
|
|
fmt.Println("1. Solana Transaction Signing")
|
|
fmt.Println(" Protocol: FROST (EdDSA on Ed25519)")
|
|
fmt.Println(" Note: Uses Taproot FROST variant for Schnorr compatibility")
|
|
fmt.Println()
|
|
|
|
// Initialize EdDSA key generation
|
|
party, err := api.KeyGen(threshold.SchemeEdDSA, "validator1", partyIDs, thresholdValue)
|
|
if err != nil {
|
|
log.Fatalf("Failed to start keygen: %v", err)
|
|
}
|
|
|
|
// Example Solana transfer transaction
|
|
tx := &SolanaTransaction{
|
|
RecentBlockhash: "EkSnNWid2cvwEVnVx9aBqawnmiCNiDgp3gUdkDPTKN1N",
|
|
FeePayer: "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin",
|
|
Instructions: []Instruction{
|
|
{
|
|
ProgramID: "11111111111111111111111111111111", // System Program
|
|
Accounts: []AccountMeta{
|
|
{Pubkey: "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin", IsSigner: true, IsWritable: true},
|
|
{Pubkey: "2wmVCSfPxGPjrnMMn7rchp4uaeoTqN39mXFC2zhPdri9", IsSigner: false, IsWritable: true},
|
|
},
|
|
Data: encodeTransferInstruction(1_000_000_000), // 1 SOL in lamports
|
|
},
|
|
},
|
|
}
|
|
|
|
// Compute transaction hash
|
|
txHash := tx.Hash()
|
|
|
|
fmt.Printf(" ✓ Key generation initiated\n")
|
|
fmt.Printf(" ✓ Transaction details:\n")
|
|
fmt.Printf(" - Fee Payer: %s...\n", tx.FeePayer[:16])
|
|
fmt.Printf(" - Recent Blockhash: %s...\n", tx.RecentBlockhash[:16])
|
|
fmt.Printf(" - Instructions: %d\n", len(tx.Instructions))
|
|
fmt.Printf(" - Amount: 1 SOL (1,000,000,000 lamports)\n")
|
|
fmt.Printf(" ✓ TX Hash: %s\n", hex.EncodeToString(txHash[:16])+"...")
|
|
fmt.Printf(" ✓ Threshold: %d-of-%d signers required\n", thresholdValue+1, len(partyIDs))
|
|
fmt.Printf(" ✓ Party status: Done=%v\n", party.Done())
|
|
fmt.Println()
|
|
|
|
// Example 2: SPL Token Transfer
|
|
fmt.Println("2. SPL Token Transfer")
|
|
fmt.Println()
|
|
|
|
splTx := &SolanaTransaction{
|
|
RecentBlockhash: "EkSnNWid2cvwEVnVx9aBqawnmiCNiDgp3gUdkDPTKN1N",
|
|
FeePayer: "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin",
|
|
Instructions: []Instruction{
|
|
{
|
|
ProgramID: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", // SPL Token Program
|
|
Accounts: []AccountMeta{
|
|
{Pubkey: "sourceTokenAccount", IsSigner: false, IsWritable: true},
|
|
{Pubkey: "destTokenAccount", IsSigner: false, IsWritable: true},
|
|
{Pubkey: "ownerPubkey", IsSigner: true, IsWritable: false},
|
|
},
|
|
Data: encodeSPLTransfer(1_000_000), // 1 USDC (6 decimals)
|
|
},
|
|
},
|
|
}
|
|
|
|
splHash := splTx.Hash()
|
|
fmt.Printf(" ✓ SPL Token transfer encoded\n")
|
|
fmt.Printf(" ✓ Token Program: TokenkegQfeZyiNwAJbNbGKPFXC...\n")
|
|
fmt.Printf(" ✓ TX Hash: %s\n", hex.EncodeToString(splHash[:16])+"...")
|
|
fmt.Println()
|
|
|
|
// Solana ecosystem
|
|
fmt.Println("=== Solana Ecosystem Support ===")
|
|
programs := []struct {
|
|
name string
|
|
programID string
|
|
}{
|
|
{"System Program", "11111111111111111111111111111111"},
|
|
{"SPL Token", "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"},
|
|
{"Token 2022", "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"},
|
|
{"Associated Token", "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"},
|
|
{"Memo Program", "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"},
|
|
}
|
|
for _, prog := range programs {
|
|
fmt.Printf(" ✓ %s\n", prog.name)
|
|
}
|
|
fmt.Println()
|
|
|
|
fmt.Println("=== Solana MPC Benefits ===")
|
|
fmt.Println(" • Native Ed25519 threshold signatures")
|
|
fmt.Println(" • Sub-second transaction finality")
|
|
fmt.Println(" • Support for all SPL tokens")
|
|
fmt.Println(" • DeFi protocol compatibility (Raydium, Jupiter, etc.)")
|
|
fmt.Println(" • NFT marketplace support (Magic Eden, Tensor)")
|
|
fmt.Println()
|
|
fmt.Println("✅ Solana threshold signing ready!")
|
|
}
|
|
|
|
// SolanaTransaction represents a simplified Solana transaction
|
|
type SolanaTransaction struct {
|
|
RecentBlockhash string
|
|
FeePayer string
|
|
Instructions []Instruction
|
|
}
|
|
|
|
// Instruction represents a Solana instruction
|
|
type Instruction struct {
|
|
ProgramID string
|
|
Accounts []AccountMeta
|
|
Data []byte
|
|
}
|
|
|
|
// AccountMeta represents account metadata
|
|
type AccountMeta struct {
|
|
Pubkey string
|
|
IsSigner bool
|
|
IsWritable bool
|
|
}
|
|
|
|
// Hash computes the transaction hash for signing
|
|
func (tx *SolanaTransaction) Hash() [32]byte {
|
|
h := sha256.New()
|
|
// Simplified: in production use proper Solana serialization
|
|
h.Write([]byte(tx.RecentBlockhash))
|
|
h.Write([]byte(tx.FeePayer))
|
|
for _, ix := range tx.Instructions {
|
|
h.Write([]byte(ix.ProgramID))
|
|
h.Write(ix.Data)
|
|
}
|
|
var result [32]byte
|
|
copy(result[:], h.Sum(nil))
|
|
return result
|
|
}
|
|
|
|
// encodeTransferInstruction encodes a System Program transfer
|
|
func encodeTransferInstruction(lamports uint64) []byte {
|
|
// Instruction: Transfer (index 2)
|
|
data := make([]byte, 12)
|
|
data[0] = 2 // Transfer instruction
|
|
// Little-endian lamports
|
|
for i := 0; i < 8; i++ {
|
|
data[4+i] = byte(lamports >> (i * 8))
|
|
}
|
|
return data
|
|
}
|
|
|
|
// encodeSPLTransfer encodes an SPL Token transfer
|
|
func encodeSPLTransfer(amount uint64) []byte {
|
|
// Instruction: Transfer (index 3)
|
|
data := make([]byte, 9)
|
|
data[0] = 3 // Transfer instruction
|
|
// Little-endian amount
|
|
for i := 0; i < 8; i++ {
|
|
data[1+i] = byte(amount >> (i * 8))
|
|
}
|
|
return data
|
|
}
|
|
|
|
// base58Alphabet is the Bitcoin/Solana base58 alphabet
|
|
const base58Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
|
|
|
// base58Encode encodes data to base58 (simplified implementation)
|
|
func base58Encode(data []byte) string {
|
|
if len(data) == 0 {
|
|
return ""
|
|
}
|
|
// Simplified: just return hex for demonstration
|
|
// Production code would use a proper base58 implementation
|
|
return hex.EncodeToString(data)
|
|
}
|