Skip to content
Open
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
73 changes: 54 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 constituted by:
// - r: 20 bytes
// - s: 32 bytes
SchnorrSigLength = 52

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not correct at the moment.

The output of the frost signature is common.SignatureData (which contains both S=32byte and R=33byte).
The processor translates it into a frost.Signature (65 byte), and stores it that way in the VAA (since we didn't export more than one signature verification function).

It is possible to convert the signature to the smart-contract format: frostsig.ToContractSig() returns S, R, and Address(R).

Does the VAA.Marshal() determine how signatures are passed to the smart contract?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, yes, VAAs are the serialized format that gets submitted to smart contracts for verification.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gather that we may be missing a conversion then, right?

)

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 == VaaVersion1 {
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 == TSSVaaVersion {
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,26 @@ 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[:])
if v.Version == 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[:])
}
} else if v.Version == TSSVaaVersion {
if len(v.Signatures) != 1 {
panic(fmt.Errorf("tried to serialize v2 VAA with %d signatures", len(v.Signatures)).Error())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is better to return an error rather than panic here (and below, too).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know what kind of errors we should be returning? I never saw code for this so I don't know the best way to do it.

}

sig := v.Signatures[0]
zeroSlice := sig.Signature[SchnorrSigLength:]
if !bytes.Equal(zeroSlice, make([]byte, len(zeroSlice))) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I follow this line.
Are you trying to ensure there are no additional bytes in sig.Signature?
If that is the case, wouldn't it be better to check the length of sig.Signature?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type definition for SignatureData forces it to be of fixed length 65 though, doesn't it? 🤔

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit wary of changing the type definition. Maybe it's not terrible to do it but I'm a bit unsure it's viable.

panic(fmt.Errorf("tried to serialize v2 VAA with invalid signature").Error())
}

buf.Write(sig.Signature[:SchnorrSigLength])
Comment thread
scnale marked this conversation as resolved.
Resolved
Comment thread
scnale marked this conversation as resolved.
Resolved
} else {
panic(fmt.Errorf("tried to serialize VAA version %d", v.Version).Error())
}

// Write Body
Expand Down
Loading