mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-21 10:27:26 +08:00
* v2.1.0 [omit consensus and adjacent] - this commit will be amended with the full release after the file copy is complete * 2.1.0 main node rollup
3081 lines
77 KiB
Go
3081 lines
77 KiB
Go
package protobufs
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
func (a *Authority) ToCanonicalBytes() ([]byte, error) {
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Write type prefix
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
AuthorityType,
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write key_type
|
|
if err := binary.Write(buf, binary.BigEndian, a.KeyType); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write public_key
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(a.PublicKey)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(a.PublicKey); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write can_burn
|
|
canBurn := byte(0)
|
|
if a.CanBurn {
|
|
canBurn = 1
|
|
}
|
|
if err := buf.WriteByte(canBurn); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func (a *Authority) FromCanonicalBytes(data []byte) error {
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
// Read and verify type prefix
|
|
var typePrefix uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &typePrefix); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if typePrefix != AuthorityType {
|
|
return errors.Wrap(
|
|
errors.New("invalid type prefix"),
|
|
"from canonical bytes",
|
|
)
|
|
}
|
|
|
|
// Read key_type
|
|
if err := binary.Read(buf, binary.BigEndian, &a.KeyType); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read public_key
|
|
var keyLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &keyLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
a.PublicKey = make([]byte, keyLen)
|
|
if _, err := buf.Read(a.PublicKey); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read can_burn
|
|
canBurn, err := buf.ReadByte()
|
|
if err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
a.CanBurn = canBurn != 0
|
|
|
|
return nil
|
|
}
|
|
|
|
func (f *FeeBasis) ToCanonicalBytes() ([]byte, error) {
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Write type prefix
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
FeeBasisStructType,
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write type
|
|
if err := binary.Write(buf, binary.BigEndian, uint32(f.Type)); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write baseline
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(f.Baseline)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(f.Baseline); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func (f *FeeBasis) FromCanonicalBytes(data []byte) error {
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
// Read and verify type prefix
|
|
var typePrefix uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &typePrefix); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if typePrefix != FeeBasisStructType {
|
|
return errors.Wrap(
|
|
errors.New("invalid type prefix"),
|
|
"from canonical bytes",
|
|
)
|
|
}
|
|
|
|
// Read type
|
|
var feeType uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &feeType); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
f.Type = FeeBasisType(feeType)
|
|
|
|
// Read baseline
|
|
var baselineLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &baselineLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
f.Baseline = make([]byte, baselineLen)
|
|
if _, err := buf.Read(f.Baseline); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (t *TokenMintStrategy) ToCanonicalBytes() ([]byte, error) {
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Write type prefix
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
TokenMintStrategyType,
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write mint_behavior
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(t.MintBehavior),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write proof_basis
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(t.ProofBasis),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write verkle_root
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.VerkleRoot)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(t.VerkleRoot); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write authority
|
|
if t.Authority != nil {
|
|
authBytes, err := t.Authority.ToCanonicalBytes()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(authBytes)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(authBytes); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
} else {
|
|
if err := binary.Write(buf, binary.BigEndian, uint32(0)); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Write payment_address
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.PaymentAddress)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(t.PaymentAddress); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write fee_basis
|
|
if t.FeeBasis != nil {
|
|
feeBytes, err := t.FeeBasis.ToCanonicalBytes()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(feeBytes)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(feeBytes); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
} else {
|
|
if err := binary.Write(buf, binary.BigEndian, uint32(0)); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func (t *TokenMintStrategy) FromCanonicalBytes(data []byte) error {
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
// Read and verify type prefix
|
|
var typePrefix uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &typePrefix); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if typePrefix != TokenMintStrategyType {
|
|
return errors.Wrap(
|
|
errors.New("invalid type prefix"),
|
|
"from canonical bytes",
|
|
)
|
|
}
|
|
|
|
// Read mint_behavior
|
|
var mintBehavior uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &mintBehavior); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.MintBehavior = TokenMintBehavior(mintBehavior)
|
|
|
|
// Read proof_basis
|
|
var proofBasis uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &proofBasis); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.ProofBasis = ProofBasisType(proofBasis)
|
|
|
|
// Read verkle_root
|
|
var verkleLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &verkleLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if verkleLen > 0 {
|
|
t.VerkleRoot = make([]byte, verkleLen)
|
|
if _, err := buf.Read(t.VerkleRoot); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read authority
|
|
var authLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &authLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if authLen > 0 {
|
|
authBytes := make([]byte, authLen)
|
|
if _, err := buf.Read(authBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.Authority = &Authority{}
|
|
if err := t.Authority.FromCanonicalBytes(authBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read payment_address
|
|
var paymentLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &paymentLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if paymentLen > 0 {
|
|
t.PaymentAddress = make([]byte, paymentLen)
|
|
if _, err := buf.Read(t.PaymentAddress); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read fee_basis
|
|
var feeLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &feeLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if feeLen > 0 {
|
|
feeBytes := make([]byte, feeLen)
|
|
if _, err := buf.Read(feeBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.FeeBasis = &FeeBasis{}
|
|
if err := t.FeeBasis.FromCanonicalBytes(feeBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (t *TokenConfiguration) ToCanonicalBytes() ([]byte, error) {
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Write type prefix
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
TokenConfigurationType,
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write behavior
|
|
if err := binary.Write(buf, binary.BigEndian, t.Behavior); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write mint_strategy
|
|
if t.MintStrategy != nil {
|
|
strategyBytes, err := t.MintStrategy.ToCanonicalBytes()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(strategyBytes)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(strategyBytes); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
} else {
|
|
if err := binary.Write(buf, binary.BigEndian, uint32(0)); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Write units
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.Units)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(t.Units); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write supply
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.Supply)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(t.Supply); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write name
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.Name)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.WriteString(t.Name); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write symbol
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.Symbol)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.WriteString(t.Symbol); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write additional_reference
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.AdditionalReference)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
for _, ref := range t.AdditionalReference {
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(ref)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(ref); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Write owner_public_key
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.OwnerPublicKey)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(t.OwnerPublicKey); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func (t *TokenConfiguration) FromCanonicalBytes(data []byte) error {
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
// Read and verify type prefix
|
|
var typePrefix uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &typePrefix); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if typePrefix != TokenConfigurationType {
|
|
return errors.Wrap(
|
|
errors.New("invalid type prefix"),
|
|
"from canonical bytes",
|
|
)
|
|
}
|
|
|
|
// Read behavior
|
|
if err := binary.Read(buf, binary.BigEndian, &t.Behavior); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read mint_strategy
|
|
var strategyLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &strategyLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if strategyLen > 0 {
|
|
strategyBytes := make([]byte, strategyLen)
|
|
if _, err := buf.Read(strategyBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.MintStrategy = &TokenMintStrategy{}
|
|
if err := t.MintStrategy.FromCanonicalBytes(strategyBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read units
|
|
var unitsLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &unitsLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if unitsLen > 0 {
|
|
t.Units = make([]byte, unitsLen)
|
|
if _, err := buf.Read(t.Units); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read supply
|
|
var supplyLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &supplyLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if supplyLen > 0 {
|
|
t.Supply = make([]byte, supplyLen)
|
|
if _, err := buf.Read(t.Supply); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read name
|
|
var nameLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &nameLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if nameLen > 0 {
|
|
nameBytes := make([]byte, nameLen)
|
|
if _, err := buf.Read(nameBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.Name = string(nameBytes)
|
|
}
|
|
|
|
// Read symbol
|
|
var symbolLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &symbolLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if symbolLen > 0 {
|
|
symbolBytes := make([]byte, symbolLen)
|
|
if _, err := buf.Read(symbolBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.Symbol = string(symbolBytes)
|
|
}
|
|
|
|
// Read additional_reference
|
|
var refCount uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &refCount); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if refCount > 0 {
|
|
t.AdditionalReference = make([][]byte, refCount)
|
|
for i := uint32(0); i < refCount; i++ {
|
|
var refLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &refLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.AdditionalReference[i] = make([]byte, refLen)
|
|
if _, err := buf.Read(t.AdditionalReference[i]); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
}
|
|
|
|
// Read owner_public_key
|
|
var ownerKeyLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &ownerKeyLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if ownerKeyLen > 0 {
|
|
t.OwnerPublicKey = make([]byte, ownerKeyLen)
|
|
if _, err := buf.Read(t.OwnerPublicKey); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (t *TokenDeploy) ToCanonicalBytes() ([]byte, error) {
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Write type prefix
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
TokenDeploymentType,
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write config
|
|
if t.Config != nil {
|
|
configBytes, err := t.Config.ToCanonicalBytes()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(configBytes)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(configBytes); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
} else {
|
|
if err := binary.Write(buf, binary.BigEndian, uint32(0)); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Write rdf_schema
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.RdfSchema)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if len(t.RdfSchema) > 0 {
|
|
if _, err := buf.Write(t.RdfSchema); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func (t *TokenDeploy) FromCanonicalBytes(data []byte) error {
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
// Read and verify type prefix
|
|
var typePrefix uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &typePrefix); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if typePrefix != TokenDeploymentType {
|
|
return errors.Wrap(
|
|
errors.New("invalid type prefix"),
|
|
"from canonical bytes",
|
|
)
|
|
}
|
|
|
|
// Read config
|
|
var configLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &configLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if configLen > 0 {
|
|
configBytes := make([]byte, configLen)
|
|
if _, err := buf.Read(configBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.Config = &TokenConfiguration{}
|
|
if err := t.Config.FromCanonicalBytes(configBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read rdf_schema
|
|
var rdfSchemaLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &rdfSchemaLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if rdfSchemaLen > 0 {
|
|
t.RdfSchema = make([]byte, rdfSchemaLen)
|
|
if _, err := buf.Read(t.RdfSchema); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (t *TokenUpdate) ToCanonicalBytes() ([]byte, error) {
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Write type prefix
|
|
if err := binary.Write(buf, binary.BigEndian, TokenUpdateType); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write config
|
|
if t.Config != nil {
|
|
configBytes, err := t.Config.ToCanonicalBytes()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(configBytes)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(configBytes); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
} else {
|
|
if err := binary.Write(buf, binary.BigEndian, uint32(0)); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Write rdf_schema
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.RdfSchema)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(t.RdfSchema); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write public_key_signature_bls48581
|
|
if t.PublicKeySignatureBls48581 != nil {
|
|
sigBytes, err := t.PublicKeySignatureBls48581.ToCanonicalBytes()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(sigBytes)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(sigBytes); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
} else {
|
|
if err := binary.Write(buf, binary.BigEndian, uint32(0)); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func (t *TokenUpdate) FromCanonicalBytes(data []byte) error {
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
// Read and verify type prefix
|
|
var typePrefix uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &typePrefix); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if typePrefix != TokenUpdateType {
|
|
return errors.Wrap(
|
|
errors.New("invalid type prefix"),
|
|
"from canonical bytes",
|
|
)
|
|
}
|
|
|
|
// Read config
|
|
var configLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &configLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if configLen > 0 {
|
|
configBytes := make([]byte, configLen)
|
|
if _, err := buf.Read(configBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.Config = &TokenConfiguration{}
|
|
if err := t.Config.FromCanonicalBytes(configBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read rdf_schema
|
|
var schemaLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &schemaLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if schemaLen > 0 {
|
|
t.RdfSchema = make([]byte, schemaLen)
|
|
if _, err := buf.Read(t.RdfSchema); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read public_key_signature_bls48581
|
|
var sigLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &sigLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if sigLen > 0 {
|
|
sigBytes := make([]byte, sigLen)
|
|
if _, err := buf.Read(sigBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.PublicKeySignatureBls48581 = &BLS48581AggregateSignature{}
|
|
if err := t.PublicKeySignatureBls48581.FromCanonicalBytes(sigBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *RecipientBundle) ToCanonicalBytes() ([]byte, error) {
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Write type prefix
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
RecipientBundleType,
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write one_time_key
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(r.OneTimeKey)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(r.OneTimeKey); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write verification_key
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(r.VerificationKey)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(r.VerificationKey); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write coin_balance
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(r.CoinBalance)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(r.CoinBalance); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write mask
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(r.Mask)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(r.Mask); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write additional_reference
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(r.AdditionalReference)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(r.AdditionalReference); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write additional_reference_key
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(r.AdditionalReferenceKey)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(r.AdditionalReferenceKey); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func (r *RecipientBundle) FromCanonicalBytes(data []byte) error {
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
// Read and verify type prefix
|
|
var typePrefix uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &typePrefix); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if typePrefix != RecipientBundleType {
|
|
return errors.Wrap(
|
|
errors.New("invalid type prefix"),
|
|
"from canonical bytes",
|
|
)
|
|
}
|
|
|
|
// Read one_time_key
|
|
var keyLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &keyLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
r.OneTimeKey = make([]byte, keyLen)
|
|
if _, err := buf.Read(r.OneTimeKey); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read verification_key
|
|
var verKeyLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &verKeyLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
r.VerificationKey = make([]byte, verKeyLen)
|
|
if _, err := buf.Read(r.VerificationKey); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read coin_balance
|
|
var balanceLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &balanceLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
r.CoinBalance = make([]byte, balanceLen)
|
|
if _, err := buf.Read(r.CoinBalance); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read mask
|
|
var maskLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &maskLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
r.Mask = make([]byte, maskLen)
|
|
if _, err := buf.Read(r.Mask); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read additional_reference
|
|
var refLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &refLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if refLen > 0 {
|
|
r.AdditionalReference = make([]byte, refLen)
|
|
if _, err := buf.Read(r.AdditionalReference); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read additional_reference_key
|
|
var refKeyLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &refKeyLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if refKeyLen > 0 {
|
|
r.AdditionalReferenceKey = make([]byte, refKeyLen)
|
|
if _, err := buf.Read(r.AdditionalReferenceKey); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (t *TransactionInput) ToCanonicalBytes() ([]byte, error) {
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Write type prefix
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
TransactionInputType,
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write commitment
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.Commitment)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(t.Commitment); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write signature
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.Signature)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(t.Signature); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write proofs count
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.Proofs)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
for _, proof := range t.Proofs {
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(proof)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(proof); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func (t *TransactionInput) FromCanonicalBytes(data []byte) error {
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
// Read and verify type prefix
|
|
var typePrefix uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &typePrefix); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if typePrefix != TransactionInputType {
|
|
return errors.Wrap(
|
|
errors.New("invalid type prefix"),
|
|
"from canonical bytes",
|
|
)
|
|
}
|
|
|
|
// Read commitment
|
|
var commitmentLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &commitmentLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.Commitment = make([]byte, commitmentLen)
|
|
if _, err := buf.Read(t.Commitment); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read signature
|
|
var sigLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &sigLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.Signature = make([]byte, sigLen)
|
|
if _, err := buf.Read(t.Signature); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read proofs
|
|
var proofsCount uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &proofsCount); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.Proofs = make([][]byte, proofsCount)
|
|
for i := uint32(0); i < proofsCount; i++ {
|
|
var proofLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &proofLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.Proofs[i] = make([]byte, proofLen)
|
|
if _, err := buf.Read(t.Proofs[i]); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (t *TransactionOutput) ToCanonicalBytes() ([]byte, error) {
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Write type prefix
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
TransactionOutputType,
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write frame_number
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.FrameNumber)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(t.FrameNumber); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write commitment
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.Commitment)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(t.Commitment); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write recipient_output
|
|
if t.RecipientOutput != nil {
|
|
recipientBytes, err := t.RecipientOutput.ToCanonicalBytes()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(recipientBytes)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(recipientBytes); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
} else {
|
|
if err := binary.Write(buf, binary.BigEndian, uint32(0)); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func (t *TransactionOutput) FromCanonicalBytes(data []byte) error {
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
// Read and verify type prefix
|
|
var typePrefix uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &typePrefix); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if typePrefix != TransactionOutputType {
|
|
return errors.Wrap(
|
|
errors.New("invalid type prefix"),
|
|
"from canonical bytes",
|
|
)
|
|
}
|
|
|
|
// Read frame_number
|
|
var frameLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &frameLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if frameLen > 0 {
|
|
t.FrameNumber = make([]byte, frameLen)
|
|
if _, err := buf.Read(t.FrameNumber); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read commitment
|
|
var commitmentLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &commitmentLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.Commitment = make([]byte, commitmentLen)
|
|
if _, err := buf.Read(t.Commitment); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read recipient_output
|
|
var recipientLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &recipientLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if recipientLen > 0 {
|
|
recipientBytes := make([]byte, recipientLen)
|
|
if _, err := buf.Read(recipientBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.RecipientOutput = &RecipientBundle{}
|
|
if err := t.RecipientOutput.FromCanonicalBytes(
|
|
recipientBytes,
|
|
); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (t *Transaction) ToCanonicalBytes() ([]byte, error) {
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Write type prefix
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
TransactionType,
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write domain
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.Domain)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(t.Domain); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write inputs count
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.Inputs)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
for _, input := range t.Inputs {
|
|
inputBytes, err := input.ToCanonicalBytes()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(inputBytes)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(inputBytes); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Write outputs count
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.Outputs)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
for _, output := range t.Outputs {
|
|
outputBytes, err := output.ToCanonicalBytes()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(outputBytes)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(outputBytes); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Write fees count
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.Fees)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
for _, fee := range t.Fees {
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(fee)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(fee); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Write range_proof
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(t.RangeProof)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(t.RangeProof); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write traversal_proof
|
|
if t.TraversalProof != nil {
|
|
traversalBytes, err := t.TraversalProof.ToCanonicalBytes()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(traversalBytes)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(traversalBytes); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
} else {
|
|
if err := binary.Write(buf, binary.BigEndian, uint32(0)); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func (t *Transaction) FromCanonicalBytes(data []byte) error {
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
// Read and verify type prefix
|
|
var typePrefix uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &typePrefix); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if typePrefix != TransactionType {
|
|
return errors.Wrap(
|
|
errors.New("invalid type prefix"),
|
|
"from canonical bytes",
|
|
)
|
|
}
|
|
|
|
// Read domain
|
|
var domainLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &domainLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.Domain = make([]byte, domainLen)
|
|
if _, err := buf.Read(t.Domain); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read inputs
|
|
var inputsCount uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &inputsCount); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.Inputs = make([]*TransactionInput, inputsCount)
|
|
for i := uint32(0); i < inputsCount; i++ {
|
|
var inputLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &inputLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
inputBytes := make([]byte, inputLen)
|
|
if _, err := buf.Read(inputBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.Inputs[i] = &TransactionInput{}
|
|
if err := t.Inputs[i].FromCanonicalBytes(inputBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read outputs
|
|
var outputsCount uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &outputsCount); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.Outputs = make([]*TransactionOutput, outputsCount)
|
|
for i := uint32(0); i < outputsCount; i++ {
|
|
var outputLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &outputLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
outputBytes := make([]byte, outputLen)
|
|
if _, err := buf.Read(outputBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.Outputs[i] = &TransactionOutput{}
|
|
if err := t.Outputs[i].FromCanonicalBytes(outputBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read fees
|
|
var feesCount uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &feesCount); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.Fees = make([][]byte, feesCount)
|
|
for i := uint32(0); i < feesCount; i++ {
|
|
var feeLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &feeLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.Fees[i] = make([]byte, feeLen)
|
|
if _, err := buf.Read(t.Fees[i]); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read range_proof
|
|
var rangeProofLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &rangeProofLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if rangeProofLen > 0 {
|
|
t.RangeProof = make([]byte, rangeProofLen)
|
|
if _, err := buf.Read(t.RangeProof); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read traversal_proof
|
|
var traversalProofLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &traversalProofLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if traversalProofLen > 0 {
|
|
traversalBytes := make([]byte, traversalProofLen)
|
|
if _, err := buf.Read(traversalBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
t.TraversalProof = &TraversalProof{}
|
|
if err := t.TraversalProof.FromCanonicalBytes(traversalBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *PendingTransactionInput) ToCanonicalBytes() ([]byte, error) {
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Write type prefix
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
PendingTransactionInputType,
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write commitment
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(p.Commitment)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(p.Commitment); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write signature
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(p.Signature)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(p.Signature); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write proofs count
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(p.Proofs)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
for _, proof := range p.Proofs {
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(proof)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(proof); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func (p *PendingTransactionInput) FromCanonicalBytes(data []byte) error {
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
// Read and verify type prefix
|
|
var typePrefix uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &typePrefix); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if typePrefix != PendingTransactionInputType {
|
|
return errors.Wrap(
|
|
errors.New("invalid type prefix"),
|
|
"from canonical bytes",
|
|
)
|
|
}
|
|
|
|
// Read commitment
|
|
var commitmentLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &commitmentLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
p.Commitment = make([]byte, commitmentLen)
|
|
if _, err := buf.Read(p.Commitment); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read signature
|
|
var sigLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &sigLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
p.Signature = make([]byte, sigLen)
|
|
if _, err := buf.Read(p.Signature); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read proofs
|
|
var proofsCount uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &proofsCount); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
p.Proofs = make([][]byte, proofsCount)
|
|
for i := uint32(0); i < proofsCount; i++ {
|
|
var proofLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &proofLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
p.Proofs[i] = make([]byte, proofLen)
|
|
if _, err := buf.Read(p.Proofs[i]); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *PendingTransactionOutput) ToCanonicalBytes() ([]byte, error) {
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Write type prefix
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
PendingTransactionOutputType,
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write frame_number
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(p.FrameNumber)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(p.FrameNumber); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write commitment
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(p.Commitment)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(p.Commitment); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write to
|
|
if p.To != nil {
|
|
toBytes, err := p.To.ToCanonicalBytes()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(toBytes)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(toBytes); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
} else {
|
|
if err := binary.Write(buf, binary.BigEndian, uint32(0)); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Write refund
|
|
if p.Refund != nil {
|
|
refundBytes, err := p.Refund.ToCanonicalBytes()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(refundBytes)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(refundBytes); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
} else {
|
|
if err := binary.Write(buf, binary.BigEndian, uint32(0)); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Write expiration
|
|
if err := binary.Write(buf, binary.BigEndian, p.Expiration); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func (p *PendingTransactionOutput) FromCanonicalBytes(data []byte) error {
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
// Read and verify type prefix
|
|
var typePrefix uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &typePrefix); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if typePrefix != PendingTransactionOutputType {
|
|
return errors.Wrap(
|
|
errors.New("invalid type prefix"),
|
|
"from canonical bytes",
|
|
)
|
|
}
|
|
|
|
// Read frame_number
|
|
var frameLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &frameLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if frameLen > 0 {
|
|
p.FrameNumber = make([]byte, frameLen)
|
|
if _, err := buf.Read(p.FrameNumber); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read commitment
|
|
var commitmentLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &commitmentLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if commitmentLen > 0 {
|
|
p.Commitment = make([]byte, commitmentLen)
|
|
if _, err := buf.Read(p.Commitment); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read to
|
|
var toLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &toLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if toLen > 0 {
|
|
toBytes := make([]byte, toLen)
|
|
if _, err := buf.Read(toBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
p.To = &RecipientBundle{}
|
|
if err := p.To.FromCanonicalBytes(toBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read refund
|
|
var refundLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &refundLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if refundLen > 0 {
|
|
refundBytes := make([]byte, refundLen)
|
|
if _, err := buf.Read(refundBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
p.Refund = &RecipientBundle{}
|
|
if err := p.Refund.FromCanonicalBytes(refundBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read expiration
|
|
if err := binary.Read(buf, binary.BigEndian, &p.Expiration); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *PendingTransaction) ToCanonicalBytes() ([]byte, error) {
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Write type prefix
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
PendingTransactionType,
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write domain
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(p.Domain)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(p.Domain); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write inputs count
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(p.Inputs)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
for _, input := range p.Inputs {
|
|
inputBytes, err := input.ToCanonicalBytes()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(inputBytes)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(inputBytes); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Write outputs count
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(p.Outputs)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
for _, output := range p.Outputs {
|
|
outputBytes, err := output.ToCanonicalBytes()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(outputBytes)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(outputBytes); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Write fees count
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(p.Fees)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
for _, fee := range p.Fees {
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(fee)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(fee); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Write range_proof
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(p.RangeProof)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(p.RangeProof); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write traversal_proof
|
|
if p.TraversalProof != nil {
|
|
traversalBytes, err := p.TraversalProof.ToCanonicalBytes()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(traversalBytes)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(traversalBytes); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
} else {
|
|
if err := binary.Write(buf, binary.BigEndian, uint32(0)); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func (p *PendingTransaction) FromCanonicalBytes(data []byte) error {
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
// Read and verify type prefix
|
|
var typePrefix uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &typePrefix); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if typePrefix != PendingTransactionType {
|
|
return errors.Wrap(
|
|
errors.New("invalid type prefix"),
|
|
"from canonical bytes",
|
|
)
|
|
}
|
|
|
|
// Read domain
|
|
var domainLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &domainLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
p.Domain = make([]byte, domainLen)
|
|
if _, err := buf.Read(p.Domain); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read inputs
|
|
var inputsCount uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &inputsCount); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
p.Inputs = make([]*PendingTransactionInput, inputsCount)
|
|
for i := uint32(0); i < inputsCount; i++ {
|
|
var inputLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &inputLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
inputBytes := make([]byte, inputLen)
|
|
if _, err := buf.Read(inputBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
p.Inputs[i] = &PendingTransactionInput{}
|
|
if err := p.Inputs[i].FromCanonicalBytes(inputBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read outputs
|
|
var outputsCount uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &outputsCount); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
p.Outputs = make([]*PendingTransactionOutput, outputsCount)
|
|
for i := uint32(0); i < outputsCount; i++ {
|
|
var outputLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &outputLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
outputBytes := make([]byte, outputLen)
|
|
if _, err := buf.Read(outputBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
p.Outputs[i] = &PendingTransactionOutput{}
|
|
if err := p.Outputs[i].FromCanonicalBytes(outputBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read fees
|
|
var feesCount uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &feesCount); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
p.Fees = make([][]byte, feesCount)
|
|
for i := uint32(0); i < feesCount; i++ {
|
|
var feeLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &feeLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
p.Fees[i] = make([]byte, feeLen)
|
|
if _, err := buf.Read(p.Fees[i]); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read range_proof
|
|
var rangeProofLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &rangeProofLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if rangeProofLen > 0 {
|
|
p.RangeProof = make([]byte, rangeProofLen)
|
|
if _, err := buf.Read(p.RangeProof); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read traversal_proof
|
|
var traversalProofLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &traversalProofLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if traversalProofLen > 0 {
|
|
traversalBytes := make([]byte, traversalProofLen)
|
|
if _, err := buf.Read(traversalBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
p.TraversalProof = &TraversalProof{}
|
|
if err := p.TraversalProof.FromCanonicalBytes(traversalBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *MintTransactionInput) ToCanonicalBytes() ([]byte, error) {
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Write type prefix
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
MintTransactionInputType,
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write value
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(m.Value)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(m.Value); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write commitment
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(m.Commitment)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(m.Commitment); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write signature
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(m.Signature)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(m.Signature); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write proofs count
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(m.Proofs)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
for _, proof := range m.Proofs {
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(proof)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(proof); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Write additional_reference
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(m.AdditionalReference)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(m.AdditionalReference); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write additional_reference_key
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(m.AdditionalReferenceKey)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(m.AdditionalReferenceKey); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func (m *MintTransactionInput) FromCanonicalBytes(data []byte) error {
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
// Read and verify type prefix
|
|
var typePrefix uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &typePrefix); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if typePrefix != MintTransactionInputType {
|
|
return errors.Wrap(
|
|
errors.New("invalid type prefix"),
|
|
"from canonical bytes",
|
|
)
|
|
}
|
|
|
|
// Read value
|
|
var valueLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &valueLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
m.Value = make([]byte, valueLen)
|
|
if _, err := buf.Read(m.Value); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read commitment
|
|
var commitmentLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &commitmentLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
m.Commitment = make([]byte, commitmentLen)
|
|
if _, err := buf.Read(m.Commitment); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read signature
|
|
var sigLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &sigLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
m.Signature = make([]byte, sigLen)
|
|
if _, err := buf.Read(m.Signature); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read proofs
|
|
var proofsCount uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &proofsCount); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
m.Proofs = make([][]byte, proofsCount)
|
|
for i := uint32(0); i < proofsCount; i++ {
|
|
var proofLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &proofLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
m.Proofs[i] = make([]byte, proofLen)
|
|
if _, err := buf.Read(m.Proofs[i]); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read additional_reference
|
|
var refKeyLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &refKeyLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if refKeyLen > 0 {
|
|
m.AdditionalReference = make([]byte, refKeyLen)
|
|
if _, err := buf.Read(m.AdditionalReference); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read additional_reference_key
|
|
var refKeyKeyLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &refKeyKeyLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if refKeyKeyLen > 0 {
|
|
m.AdditionalReferenceKey = make([]byte, refKeyKeyLen)
|
|
if _, err := buf.Read(
|
|
m.AdditionalReferenceKey,
|
|
); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *MintTransactionOutput) ToCanonicalBytes() ([]byte, error) {
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Write type prefix
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
MintTransactionOutputType,
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write frame_number
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(m.FrameNumber)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(m.FrameNumber); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write commitment
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(m.Commitment)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(m.Commitment); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write recipient_output
|
|
if m.RecipientOutput != nil {
|
|
recipientBytes, err := m.RecipientOutput.ToCanonicalBytes()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(recipientBytes)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(recipientBytes); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
} else {
|
|
if err := binary.Write(buf, binary.BigEndian, uint32(0)); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func (m *MintTransactionOutput) FromCanonicalBytes(data []byte) error {
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
// Read and verify type prefix
|
|
var typePrefix uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &typePrefix); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if typePrefix != MintTransactionOutputType {
|
|
return errors.Wrap(
|
|
errors.New("invalid type prefix"),
|
|
"from canonical bytes",
|
|
)
|
|
}
|
|
|
|
// Read frame_number
|
|
var frameLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &frameLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if frameLen > 0 {
|
|
m.FrameNumber = make([]byte, frameLen)
|
|
if _, err := buf.Read(m.FrameNumber); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read commitment
|
|
var commitmentLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &commitmentLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
m.Commitment = make([]byte, commitmentLen)
|
|
if _, err := buf.Read(m.Commitment); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read recipient_output
|
|
var recipientLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &recipientLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if recipientLen > 0 {
|
|
recipientBytes := make([]byte, recipientLen)
|
|
if _, err := buf.Read(recipientBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
m.RecipientOutput = &RecipientBundle{}
|
|
if err := m.RecipientOutput.FromCanonicalBytes(
|
|
recipientBytes,
|
|
); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *MintTransaction) ToCanonicalBytes() ([]byte, error) {
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Write type prefix
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
MintTransactionType,
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write domain
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(m.Domain)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(m.Domain); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
// Write inputs count
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(m.Inputs)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
for _, input := range m.Inputs {
|
|
inputBytes, err := input.ToCanonicalBytes()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(inputBytes)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(inputBytes); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Write outputs count
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(m.Outputs)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
for _, output := range m.Outputs {
|
|
outputBytes, err := output.ToCanonicalBytes()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(outputBytes)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(outputBytes); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Write fees count
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(m.Fees)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
for _, fee := range m.Fees {
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(fee)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(fee); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Write range_proof
|
|
if err := binary.Write(
|
|
buf,
|
|
binary.BigEndian,
|
|
uint32(len(m.RangeProof)),
|
|
); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
if _, err := buf.Write(m.RangeProof); err != nil {
|
|
return nil, errors.Wrap(err, "to canonical bytes")
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func (m *MintTransaction) FromCanonicalBytes(data []byte) error {
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
// Read and verify type prefix
|
|
var typePrefix uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &typePrefix); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if typePrefix != MintTransactionType {
|
|
return errors.Wrap(
|
|
errors.New("invalid type prefix"),
|
|
"from canonical bytes",
|
|
)
|
|
}
|
|
|
|
// Read domain
|
|
var domainLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &domainLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
m.Domain = make([]byte, domainLen)
|
|
if _, err := buf.Read(m.Domain); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
|
|
// Read inputs
|
|
var inputsCount uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &inputsCount); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
m.Inputs = make([]*MintTransactionInput, inputsCount)
|
|
for i := uint32(0); i < inputsCount; i++ {
|
|
var inputLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &inputLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
inputBytes := make([]byte, inputLen)
|
|
if _, err := buf.Read(inputBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
m.Inputs[i] = &MintTransactionInput{}
|
|
if err := m.Inputs[i].FromCanonicalBytes(inputBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read outputs
|
|
var outputsCount uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &outputsCount); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
m.Outputs = make([]*MintTransactionOutput, outputsCount)
|
|
for i := uint32(0); i < outputsCount; i++ {
|
|
var outputLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &outputLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
outputBytes := make([]byte, outputLen)
|
|
if _, err := buf.Read(outputBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
m.Outputs[i] = &MintTransactionOutput{}
|
|
if err := m.Outputs[i].FromCanonicalBytes(outputBytes); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read fees
|
|
var feesCount uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &feesCount); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
m.Fees = make([][]byte, feesCount)
|
|
for i := uint32(0); i < feesCount; i++ {
|
|
var feeLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &feeLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
m.Fees[i] = make([]byte, feeLen)
|
|
if _, err := buf.Read(m.Fees[i]); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
// Read range_proof
|
|
var rangeProofLen uint32
|
|
if err := binary.Read(buf, binary.BigEndian, &rangeProofLen); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
if rangeProofLen > 0 {
|
|
m.RangeProof = make([]byte, rangeProofLen)
|
|
if _, err := buf.Read(m.RangeProof); err != nil {
|
|
return errors.Wrap(err, "from canonical bytes")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
var _ ValidatableMessage = (*Authority)(nil)
|
|
|
|
func (a *Authority) Validate() error {
|
|
if a == nil {
|
|
return errors.Wrap(errors.New("nil authority"), "validate")
|
|
}
|
|
|
|
// Validate public key based on key type
|
|
switch a.KeyType {
|
|
case 0: // Ed448
|
|
if len(a.PublicKey) != 57 {
|
|
return errors.Wrap(
|
|
errors.New("invalid ed448 public key length"),
|
|
"validate",
|
|
)
|
|
}
|
|
default:
|
|
return errors.Wrap(
|
|
errors.New("unsupported key type"),
|
|
"validate",
|
|
)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
var _ ValidatableMessage = (*FeeBasis)(nil)
|
|
|
|
func (f *FeeBasis) Validate() error {
|
|
if f == nil {
|
|
return errors.Wrap(errors.New("nil fee basis"), "validate")
|
|
}
|
|
|
|
// Validate fee type
|
|
switch f.Type {
|
|
case FeeBasisType_NO_FEE_BASIS:
|
|
// No baseline needed
|
|
case FeeBasisType_PER_UNIT:
|
|
if len(f.Baseline) == 0 {
|
|
return errors.Wrap(
|
|
errors.New("baseline required for per unit fee"),
|
|
"validate",
|
|
)
|
|
}
|
|
default:
|
|
return errors.Wrap(errors.New("invalid fee basis type"), "validate")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
var _ ValidatableMessage = (*TokenMintStrategy)(nil)
|
|
|
|
func (t *TokenMintStrategy) Validate() error {
|
|
if t == nil {
|
|
return errors.Wrap(errors.New("nil token mint strategy"), "validate")
|
|
}
|
|
|
|
// Validate mint behavior
|
|
switch t.MintBehavior {
|
|
case TokenMintBehavior_NO_MINT_BEHAVIOR:
|
|
// No additional validation needed
|
|
case TokenMintBehavior_MINT_WITH_PROOF:
|
|
// Verkle root is optional
|
|
case TokenMintBehavior_MINT_WITH_AUTHORITY:
|
|
if t.Authority == nil {
|
|
return errors.Wrap(
|
|
errors.New("authority required for authority mint"),
|
|
"validate",
|
|
)
|
|
}
|
|
if err := t.Authority.Validate(); err != nil {
|
|
return errors.Wrap(err, "authority")
|
|
}
|
|
case TokenMintBehavior_MINT_WITH_SIGNATURE:
|
|
if t.Authority == nil {
|
|
return errors.Wrap(
|
|
errors.New("authority required for signature mint"),
|
|
"validate",
|
|
)
|
|
}
|
|
if err := t.Authority.Validate(); err != nil {
|
|
return errors.Wrap(err, "validate")
|
|
}
|
|
case TokenMintBehavior_MINT_WITH_PAYMENT:
|
|
if len(t.PaymentAddress) == 0 {
|
|
return errors.Wrap(
|
|
errors.New("payment address required for payment mint"),
|
|
"validate",
|
|
)
|
|
}
|
|
if t.FeeBasis == nil {
|
|
return errors.Wrap(
|
|
errors.New("fee basis required for payment mint"),
|
|
"validate",
|
|
)
|
|
}
|
|
if err := t.FeeBasis.Validate(); err != nil {
|
|
return errors.Wrap(err, "fee basis")
|
|
}
|
|
default:
|
|
return errors.Wrap(errors.New("invalid mint behavior"), "validate")
|
|
}
|
|
|
|
// Validate proof basis
|
|
switch t.ProofBasis {
|
|
case ProofBasisType_NO_PROOF_BASIS:
|
|
// No additional validation needed
|
|
case ProofBasisType_PROOF_OF_MEANINGFUL_WORK:
|
|
// No additional validation needed
|
|
case ProofBasisType_VERKLE_MULTIPROOF_WITH_SIGNATURE:
|
|
if len(t.VerkleRoot) == 0 {
|
|
return errors.Wrap(
|
|
errors.New("verkle root required for verkle proof basis"),
|
|
"validate",
|
|
)
|
|
}
|
|
default:
|
|
return errors.Wrap(errors.New("invalid proof basis type"), "validate")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
var _ ValidatableMessage = (*TokenConfiguration)(nil)
|
|
|
|
func (t *TokenConfiguration) Validate() error {
|
|
if t == nil {
|
|
return errors.Wrap(errors.New("nil token configuration"), "validate")
|
|
}
|
|
|
|
// Check if mintable flag is set
|
|
isMintable := (t.Behavior & uint32(
|
|
TokenIntrinsicBehavior_TOKEN_BEHAVIOR_MINTABLE,
|
|
)) != 0
|
|
|
|
if isMintable {
|
|
if t.MintStrategy == nil {
|
|
return errors.Wrap(
|
|
errors.New("mint strategy required for mintable token"),
|
|
"validate",
|
|
)
|
|
}
|
|
if err := t.MintStrategy.Validate(); err != nil {
|
|
return errors.Wrap(err, "validate")
|
|
}
|
|
} else {
|
|
// Non-mintable tokens must have supply
|
|
if len(t.Supply) == 0 {
|
|
return errors.Wrap(
|
|
errors.New("supply required for non-mintable token"),
|
|
"validate",
|
|
)
|
|
}
|
|
}
|
|
|
|
// Check if divisible flag is set
|
|
isDivisible := (t.Behavior & uint32(
|
|
TokenIntrinsicBehavior_TOKEN_BEHAVIOR_DIVISIBLE,
|
|
)) != 0
|
|
|
|
if isDivisible {
|
|
if len(t.Units) == 0 {
|
|
return errors.Wrap(
|
|
errors.New("units required for divisible token"),
|
|
"validate",
|
|
)
|
|
}
|
|
}
|
|
|
|
// Validate metadata
|
|
if len(t.Name) == 0 {
|
|
return errors.Wrap(errors.New("token name required"), "validate")
|
|
}
|
|
|
|
if len(t.Symbol) == 0 {
|
|
return errors.Wrap(errors.New("token symbol required"), "validate")
|
|
}
|
|
|
|
// Each additional reference should be 64 bytes if provided
|
|
for i, ref := range t.AdditionalReference {
|
|
if len(ref) != 64 {
|
|
return errors.Wrapf(
|
|
errors.New("additional reference must be 64 bytes"),
|
|
"validate: reference %d has %d bytes",
|
|
i, len(ref),
|
|
)
|
|
}
|
|
}
|
|
|
|
// Validate owner public key (0 or 585 bytes for BLS48-581)
|
|
if len(t.OwnerPublicKey) != 0 && len(t.OwnerPublicKey) != 585 {
|
|
return errors.Wrap(
|
|
errors.New("owner public key must be 0 or 585 bytes"),
|
|
"validate",
|
|
)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
var _ ValidatableMessage = (*TokenDeploy)(nil)
|
|
|
|
func (t *TokenDeploy) Validate() error {
|
|
if t == nil {
|
|
return errors.Wrap(errors.New("nil token deploy"), "validate")
|
|
}
|
|
|
|
if t.Config == nil {
|
|
return errors.Wrap(errors.New("nil configuration"), "validate")
|
|
}
|
|
|
|
return t.Config.Validate()
|
|
}
|
|
|
|
var _ ValidatableMessage = (*TokenUpdate)(nil)
|
|
|
|
func (t *TokenUpdate) Validate() error {
|
|
if t == nil {
|
|
return errors.Wrap(errors.New("nil token update"), "validate")
|
|
}
|
|
|
|
// Config is required for token updates
|
|
if t.Config == nil {
|
|
return errors.Wrap(errors.New("nil configuration"), "validate")
|
|
}
|
|
|
|
if err := t.Config.Validate(); err != nil {
|
|
return errors.Wrap(err, "validate")
|
|
}
|
|
|
|
if t.PublicKeySignatureBls48581 == nil {
|
|
return errors.Wrap(errors.New("public key signature is nil"), "validate")
|
|
}
|
|
|
|
if err := t.PublicKeySignatureBls48581.Validate(); err != nil {
|
|
return errors.Wrap(err, "validate")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
var _ ValidatableMessage = (*RecipientBundle)(nil)
|
|
|
|
func (r *RecipientBundle) Validate() error {
|
|
if r == nil {
|
|
return errors.Wrap(errors.New("nil recipient bundle"), "validate")
|
|
}
|
|
|
|
// OneTimeKey should not be empty
|
|
if len(r.OneTimeKey) == 0 {
|
|
return errors.Wrap(errors.New("one time key required"), "validate")
|
|
}
|
|
|
|
// VerificationKey should not be empty
|
|
if len(r.VerificationKey) == 0 {
|
|
return errors.Wrap(errors.New("verification key required"), "validate")
|
|
}
|
|
|
|
// CoinBalance should not be empty
|
|
if len(r.CoinBalance) == 0 {
|
|
return errors.Wrap(errors.New("coin balance required"), "validate")
|
|
}
|
|
|
|
// Mask should not be empty
|
|
if len(r.Mask) == 0 {
|
|
return errors.Wrap(errors.New("mask required"), "validate")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
var _ ValidatableMessage = (*TransactionInput)(nil)
|
|
|
|
func (t *TransactionInput) Validate() error {
|
|
if t == nil {
|
|
return errors.Wrap(errors.New("nil transaction input"), "validate")
|
|
}
|
|
|
|
if len(t.Commitment) == 0 {
|
|
return errors.Wrap(errors.New("commitment required"), "validate")
|
|
}
|
|
|
|
if len(t.Signature) == 0 {
|
|
return errors.Wrap(errors.New("signature required"), "validate")
|
|
}
|
|
|
|
// Proofs can be empty
|
|
|
|
return nil
|
|
}
|
|
|
|
var _ ValidatableMessage = (*TransactionOutput)(nil)
|
|
|
|
func (t *TransactionOutput) Validate() error {
|
|
if t == nil {
|
|
return errors.Wrap(errors.New("nil transaction output"), "validate")
|
|
}
|
|
|
|
// FrameNumber can be empty (for pending outputs)
|
|
|
|
if len(t.Commitment) == 0 {
|
|
return errors.Wrap(errors.New("commitment required"), "validate")
|
|
}
|
|
|
|
if t.RecipientOutput != nil {
|
|
if err := t.RecipientOutput.Validate(); err != nil {
|
|
return errors.Wrap(err, "validate")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
var _ ValidatableMessage = (*Transaction)(nil)
|
|
|
|
func (t *Transaction) Validate() error {
|
|
if t == nil {
|
|
return errors.Wrap(errors.New("nil transaction"), "validate")
|
|
}
|
|
|
|
// Validate domain (32 bytes)
|
|
if len(t.Domain) != 32 {
|
|
return errors.Wrap(errors.New("invalid domain length"), "validate")
|
|
}
|
|
|
|
// Must have at least one input
|
|
if len(t.Inputs) == 0 {
|
|
return errors.Wrap(errors.New("no inputs"), "validate")
|
|
}
|
|
|
|
// Validate all inputs
|
|
for i, input := range t.Inputs {
|
|
if err := input.Validate(); err != nil {
|
|
return errors.Wrap(errors.Wrapf(err, "input %d", i), "validate")
|
|
}
|
|
}
|
|
|
|
// Must have at least one output
|
|
if len(t.Outputs) == 0 {
|
|
return errors.Wrap(errors.New("no outputs"), "validate")
|
|
}
|
|
|
|
// Validate all outputs
|
|
for i, output := range t.Outputs {
|
|
if err := output.Validate(); err != nil {
|
|
return errors.Wrap(errors.Wrapf(err, "output %d", i), "validate")
|
|
}
|
|
}
|
|
|
|
// Fees array should match outputs
|
|
if len(t.Fees) != len(t.Outputs) {
|
|
return errors.Wrap(
|
|
errors.New("fees count must match outputs count"),
|
|
"validate",
|
|
)
|
|
}
|
|
|
|
// Range proof is required
|
|
if len(t.RangeProof) == 0 {
|
|
return errors.Wrap(errors.New("range proof required"), "validate")
|
|
}
|
|
|
|
// TraversalProof is optional
|
|
|
|
return nil
|
|
}
|
|
|
|
var _ ValidatableMessage = (*PendingTransactionInput)(nil)
|
|
|
|
func (p *PendingTransactionInput) Validate() error {
|
|
if p == nil {
|
|
return errors.Wrap(errors.New("nil pending transaction input"), "validate")
|
|
}
|
|
|
|
if len(p.Commitment) == 0 {
|
|
return errors.Wrap(errors.New("commitment required"), "validate")
|
|
}
|
|
|
|
if len(p.Signature) == 0 {
|
|
return errors.Wrap(errors.New("signature required"), "validate")
|
|
}
|
|
|
|
// Proofs can be empty
|
|
|
|
return nil
|
|
}
|
|
|
|
var _ ValidatableMessage = (*PendingTransactionOutput)(nil)
|
|
|
|
func (p *PendingTransactionOutput) Validate() error {
|
|
if p == nil {
|
|
return errors.Wrap(
|
|
errors.New("nil pending transaction output"),
|
|
"validate",
|
|
)
|
|
}
|
|
|
|
// FrameNumber can be empty (for pending outputs)
|
|
|
|
if p.To == nil {
|
|
return errors.Wrap(errors.New("to recipient required"), "validate")
|
|
}
|
|
if err := p.To.Validate(); err != nil {
|
|
return errors.Wrap(err, "to recipient")
|
|
}
|
|
|
|
if p.Refund == nil {
|
|
return errors.Wrap(errors.New("refund recipient required"), "validate")
|
|
}
|
|
if err := p.Refund.Validate(); err != nil {
|
|
return errors.Wrap(err, "refund recipient")
|
|
}
|
|
|
|
// Expiration is checked only if token is expirable
|
|
|
|
return nil
|
|
}
|
|
|
|
var _ ValidatableMessage = (*PendingTransaction)(nil)
|
|
|
|
func (p *PendingTransaction) Validate() error {
|
|
if p == nil {
|
|
return errors.Wrap(errors.New("nil pending transaction"), "validate")
|
|
}
|
|
|
|
// Validate domain (32 bytes)
|
|
if len(p.Domain) != 32 {
|
|
return errors.Wrap(errors.New("invalid domain length"), "validate")
|
|
}
|
|
|
|
// Must have at least one input
|
|
if len(p.Inputs) == 0 {
|
|
return errors.Wrap(errors.New("no inputs"), "validate")
|
|
}
|
|
|
|
// Validate all inputs
|
|
for i, input := range p.Inputs {
|
|
if err := input.Validate(); err != nil {
|
|
return errors.Wrap(errors.Wrapf(err, "input %d", i), "validate")
|
|
}
|
|
}
|
|
|
|
// Must have at least one output
|
|
if len(p.Outputs) == 0 {
|
|
return errors.Wrap(errors.New("no outputs"), "validate")
|
|
}
|
|
|
|
// Validate all outputs
|
|
for i, output := range p.Outputs {
|
|
if err := output.Validate(); err != nil {
|
|
return errors.Wrap(errors.Wrapf(err, "output %d", i), "validate")
|
|
}
|
|
}
|
|
|
|
// Fees array should match outputs
|
|
if len(p.Fees) != len(p.Outputs) {
|
|
return errors.Wrap(
|
|
errors.New("fees count must match outputs count"),
|
|
"validate",
|
|
)
|
|
}
|
|
|
|
// Range proof is required
|
|
if len(p.RangeProof) == 0 {
|
|
return errors.Wrap(errors.New("range proof required"), "validate")
|
|
}
|
|
|
|
// TraversalProof is optional
|
|
|
|
return nil
|
|
}
|
|
|
|
var _ ValidatableMessage = (*MintTransactionInput)(nil)
|
|
|
|
func (m *MintTransactionInput) Validate() error {
|
|
if m == nil {
|
|
return errors.Wrap(errors.New("nil mint transaction input"), "validate")
|
|
}
|
|
|
|
if len(m.Value) == 0 {
|
|
return errors.Wrap(errors.New("value required"), "validate")
|
|
}
|
|
|
|
if len(m.Commitment) == 0 {
|
|
return errors.Wrap(errors.New("commitment required"), "validate")
|
|
}
|
|
|
|
if len(m.Signature) == 0 {
|
|
return errors.Wrap(errors.New("signature required"), "validate")
|
|
}
|
|
|
|
// Proofs can be empty
|
|
// Additional reference encryption keys are optional
|
|
|
|
return nil
|
|
}
|
|
|
|
var _ ValidatableMessage = (*MintTransactionOutput)(nil)
|
|
|
|
func (m *MintTransactionOutput) Validate() error {
|
|
if m == nil {
|
|
return errors.Wrap(errors.New("nil mint transaction output"), "validate")
|
|
}
|
|
|
|
// FrameNumber can be empty (for pending outputs)
|
|
|
|
if len(m.Commitment) == 0 {
|
|
return errors.Wrap(errors.New("commitment required"), "validate")
|
|
}
|
|
|
|
if m.RecipientOutput != nil {
|
|
if err := m.RecipientOutput.Validate(); err != nil {
|
|
return errors.Wrap(err, "validate")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
var _ ValidatableMessage = (*MintTransaction)(nil)
|
|
|
|
func (m *MintTransaction) Validate() error {
|
|
if m == nil {
|
|
return errors.Wrap(errors.New("nil mint transaction"), "validate")
|
|
}
|
|
|
|
// Validate domain (32 bytes)
|
|
if len(m.Domain) != 32 {
|
|
return errors.Wrap(errors.New("invalid domain length"), "validate")
|
|
}
|
|
|
|
// Must have at least one input
|
|
if len(m.Inputs) == 0 {
|
|
return errors.Wrap(errors.New("no inputs"), "validate")
|
|
}
|
|
|
|
// Validate all inputs
|
|
for i, input := range m.Inputs {
|
|
if err := input.Validate(); err != nil {
|
|
return errors.Wrap(errors.Wrapf(err, "input %d", i), "validate")
|
|
}
|
|
}
|
|
|
|
// Must have at least one output
|
|
if len(m.Outputs) == 0 {
|
|
return errors.Wrap(errors.New("no outputs"), "validate")
|
|
}
|
|
|
|
// Validate all outputs
|
|
for i, output := range m.Outputs {
|
|
if err := output.Validate(); err != nil {
|
|
return errors.Wrap(errors.Wrapf(err, "output %d", i), "validate")
|
|
}
|
|
}
|
|
|
|
// Fees array should match outputs
|
|
if len(m.Fees) != len(m.Outputs) {
|
|
return errors.Wrap(
|
|
errors.New("fees count must match outputs count"),
|
|
"validate",
|
|
)
|
|
}
|
|
|
|
// Range proof is required
|
|
if len(m.RangeProof) == 0 {
|
|
return errors.Wrap(errors.New("range proof required"), "validate")
|
|
}
|
|
|
|
return nil
|
|
}
|