Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions node/pkg/tss/implementation.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ type Configurations struct {
// LeaderIdentity is used by the TSS engine protocol to determine who is responsible for telling
// the other guardians about a new VAAv1.
LeaderIdentity PEM // The public key of the leader in PEM format.

// AllowedChainIDs is a map of chain IDs that the TSS signer is allowed to sign.
// If nil or empty, TSS is disabled for all chains.
// The key is the chain ID, and the value should be true for allowed chains.
AllowedChainIDs map[vaa.ChainID]bool
}

// GuardianStorage is a struct that holds the data needed for a guardian to participate in the TSS protocol
Expand Down Expand Up @@ -164,6 +169,23 @@ func (t *Engine) beginTSSSign(vaaDigest []byte, chainID vaa.ChainID, consistency
return fmt.Errorf("vaaDigest length is not 32 bytes")
}

// Check if this chain ID is allowed for TSS signing
if len(t.AllowedChainIDs) > 0 {
if !t.AllowedChainIDs[chainID] {
t.logger.Info("skipping TSS signing for filtered chain ID",
zap.String("chainID", chainID.String()),
zap.String("digest", fmt.Sprintf("%x", vaaDigest)),
)
return nil
}
} else {
t.logger.Info("TSS signing is disabled for all chains",
zap.String("chainID", chainID.String()),
zap.String("digest", fmt.Sprintf("%x", vaaDigest)),
)
return nil
}

d := party.Digest{}
copy(d[:], vaaDigest)

Expand Down
74 changes: 55 additions & 19 deletions sdk/vaa/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,11 @@ const (
// TSSVaaVersion uses a threshold signature scheme to sign the VAA struct.
// As a result, a valid VAA would result in a single signature.
TSSVaaVersion = 0x02

// The schnorr signature is consituted by:
// - r: 20 bytes
// - s: 32 bytes
SchnorrSigLength = 52
)

var SupportedVAAVersions = map[uint8]bool{VaaVersion1: true, TSSVaaVersion: true}
Expand Down Expand Up @@ -474,27 +479,41 @@ func Unmarshal(data []byte) (*VAA, error) {
return nil, fmt.Errorf("failed to read guardian set index: %w", err)
}

lenSignatures, er := reader.ReadByte()
if er != nil {
return nil, fmt.Errorf("failed to read signature length")
}

v.Signatures = make([]*Signature, lenSignatures)
for i := 0; i < int(lenSignatures); i++ {
index, err := reader.ReadByte()
if err != nil {
return nil, fmt.Errorf("failed to read validator index [%d]", i)
if v.Version == 1 {
lenSignatures, er := reader.ReadByte()
if er != nil {
return nil, fmt.Errorf("failed to read signature length")
}

v.Signatures = make([]*Signature, lenSignatures)
for i := 0; i < int(lenSignatures); i++ {
index, err := reader.ReadByte()
if err != nil {
return nil, fmt.Errorf("failed to read validator index [%d]", i)
}

signature := [65]byte{}
if n, err := reader.Read(signature[:]); err != nil || n != 65 {
return nil, fmt.Errorf("failed to read signature [%d]: %w", i, err)
}

v.Signatures[i] = &Signature{
Index: index,
Signature: signature,
}
}
} else if v.Version == 2 {
v.Signatures = make([]*Signature, 1)
signature := [65]byte{}
if n, err := reader.Read(signature[:]); err != nil || n != 65 {
return nil, fmt.Errorf("failed to read signature [%d]: %w", i, err)
if n, err := reader.Read(signature[:SchnorrSigLength]); err != nil || n != SchnorrSigLength {
return nil, fmt.Errorf("failed to read schnorr signature: %w", err)
}

v.Signatures[i] = &Signature{
Index: index,
v.Signatures[0] = &Signature{
Index: 0,
Signature: signature,
}
} else {
return nil, fmt.Errorf("failed to read VAA version %d", v.Version)
}

return UnmarshalBody(data, reader, v)
Expand Down Expand Up @@ -707,10 +726,27 @@ func (v *VAA) Marshal() ([]byte, error) {
MustWrite(buf, binary.BigEndian, v.GuardianSetIndex)

// Write signatures
MustWrite(buf, binary.BigEndian, uint8(len(v.Signatures))) // #nosec G115 -- There will never be 256 guardians
for _, sig := range v.Signatures {
MustWrite(buf, binary.BigEndian, sig.Index)
buf.Write(sig.Signature[:])
switch v.Version {
case VaaVersion1:
MustWrite(buf, binary.BigEndian, uint8(len(v.Signatures))) // #nosec G115 -- There will never be 256 guardians
for _, sig := range v.Signatures {
MustWrite(buf, binary.BigEndian, sig.Index)
buf.Write(sig.Signature[:])
}
case TSSVaaVersion:
if len(v.Signatures) != 1 {
panic(fmt.Errorf("tried to serialize v2 VAA with %d signatures", len(v.Signatures)).Error())
}

sig := v.Signatures[0]
zeroSlice := sig.Signature[SchnorrSigLength:]
if !bytes.Equal(zeroSlice, make([]byte, len(zeroSlice))) {
panic(fmt.Errorf("tried to serialize v2 VAA with invalid signature").Error())
}

buf.Write(sig.Signature[:SchnorrSigLength])
default:
panic(fmt.Errorf("tried to serialize VAA version %d", v.Version).Error())
}

// Write Body
Expand Down
Loading