|
1 | 1 | package sui
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "crypto/ed25519" |
| 5 | + "encoding/base64" |
4 | 6 | "encoding/hex"
|
5 |
| - "errors" |
6 | 7 | "fmt"
|
7 | 8 |
|
8 |
| - "github.com/block-vision/sui-go-sdk/constant" |
9 | 9 | "github.com/block-vision/sui-go-sdk/signer"
|
| 10 | + "golang.org/x/crypto/blake2b" |
10 | 11 | )
|
11 | 12 |
|
12 | 13 | // TODO: Everything in this file should come from chainlink-sui when available
|
@@ -45,23 +46,67 @@ func NewSignerFromHexPrivateKey(hexPrivateKey string) (SuiSigner, error) {
|
45 | 46 | }
|
46 | 47 |
|
47 | 48 | func (s *suiSigner) Sign(message []byte) ([]string, error) {
|
48 |
| - if s.signer == nil { |
49 |
| - return nil, errors.New("signer is nil") |
50 |
| - } |
| 49 | + // Add intent scope for transaction data (0x00, 0x00, 0x00) |
| 50 | + intentMessage := append([]byte{0x00, 0x00, 0x00}, message...) |
51 | 51 |
|
52 |
| - // Sign the message as a transaction message |
53 |
| - signedMsg, err := s.signer.SignMessage(string(message), constant.TransactionDataIntentScope) |
54 |
| - if err != nil { |
55 |
| - return nil, fmt.Errorf("failed to sign message: %w", err) |
56 |
| - } |
| 52 | + // Hash the message with blake2b |
| 53 | + hash := blake2b.Sum256(intentMessage) |
| 54 | + |
| 55 | + // Sign the hash |
| 56 | + signature := ed25519.Sign(s.signer.PriKey, hash[:]) |
57 | 57 |
|
58 |
| - return []string{signedMsg.Signature}, nil |
| 58 | + // Get public key |
| 59 | + publicKey := s.signer.PriKey.Public().(ed25519.PublicKey) |
| 60 | + |
| 61 | + // Create serialized signature: flag + signature + pubkey |
| 62 | + serializedSig := make([]byte, 1+len(signature)+len(publicKey)) |
| 63 | + serializedSig[0] = 0x00 // Ed25519 flag |
| 64 | + copy(serializedSig[1:], signature) |
| 65 | + copy(serializedSig[1+len(signature):], publicKey) |
| 66 | + |
| 67 | + // Encode to base64 |
| 68 | + encoded := base64.StdEncoding.EncodeToString(serializedSig) |
| 69 | + |
| 70 | + return []string{encoded}, nil |
59 | 71 | }
|
60 | 72 |
|
61 | 73 | func (s *suiSigner) GetAddress() (string, error) {
|
62 |
| - if s.signer == nil { |
63 |
| - return "", errors.New("signer is nil") |
| 74 | + publicKey := s.signer.PriKey.Public().(ed25519.PublicKey) |
| 75 | + |
| 76 | + // For Ed25519, the signature scheme is 0x00 |
| 77 | + const signatureScheme = 0x00 |
| 78 | + |
| 79 | + // Create the data to hash: signature scheme byte || public key |
| 80 | + data := append([]byte{signatureScheme}, publicKey...) |
| 81 | + |
| 82 | + // Hash using Blake2b-256 |
| 83 | + hash := blake2b.Sum256(data) |
| 84 | + |
| 85 | + // The Sui address is the hex representation of the hash |
| 86 | + return "0x" + hex.EncodeToString(hash[:]), nil |
| 87 | +} |
| 88 | + |
| 89 | +// PublicKeyBytes extracts the raw 32-byte ed25519 public key from a SuiSigner. |
| 90 | +func PublicKeyBytes(s SuiSigner) ([]byte, error) { |
| 91 | + impl, ok := s.(*suiSigner) |
| 92 | + if !ok { |
| 93 | + return nil, fmt.Errorf("unsupported signer type %T", s) |
| 94 | + } |
| 95 | + priv := []byte(impl.signer.PriKey) |
| 96 | + if len(priv) != ed25519.PrivateKeySize { |
| 97 | + return nil, fmt.Errorf("unexpected ed25519 key length: %d", len(priv)) |
64 | 98 | }
|
| 99 | + pub := make([]byte, ed25519.PublicKeySize) |
| 100 | + copy(pub, priv[32:]) // last 32 bytes are the pubkey |
| 101 | + return pub, nil |
| 102 | +} |
65 | 103 |
|
66 |
| - return s.signer.Address, nil |
| 104 | +// PrivateKey returns the underlying ed25519.PrivateKey (64 bytes = seed||pubkey) |
| 105 | +// from a SuiSigner created in this package. |
| 106 | +func PrivateKey(s SuiSigner) (ed25519.PrivateKey, error) { |
| 107 | + impl, ok := s.(*suiSigner) |
| 108 | + if !ok { |
| 109 | + return nil, fmt.Errorf("unsupported signer type %T", s) |
| 110 | + } |
| 111 | + return impl.signer.PriKey, nil |
67 | 112 | }
|
0 commit comments