Skip to content

Commit

Permalink
Add transactions multi-signing. (#76)
Browse files Browse the repository at this point in the history
* Add transaction multi-signing.
* Add `MultiSign` and `SetSigners` methods for transactions to be signed from multi-signing.
* Add additional `MultiSignable` interface for the `BaseTx` and implement it.
*  Fix structure used by `SIGNER_LIST_SET`  and `multi-signing`
*  Add missing `temBAD_WEIGHT` error code
  • Loading branch information
dzmitryhil committed Sep 6, 2023
1 parent 85936e0 commit c77e440
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 25 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@ _testmain.go
*.coverprofile

.DS_Store

# IDE specific
.idea
*.iml
17 changes: 12 additions & 5 deletions data/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,20 @@ import (
)

func Raw(h Hashable) (Hash256, []byte, error) {
return raw(h, h.Prefix(), false)
return raw(h, h.Prefix(), nil, false)
}

func NodeId(h Hashable) (Hash256, error) {
nodeid, _, err := raw(h, h.Prefix(), false)
nodeid, _, err := raw(h, h.Prefix(), nil, false)
return nodeid, err
}

func SigningHash(s Signable) (Hash256, []byte, error) {
return raw(s, s.SigningPrefix(), true)
return raw(s, s.SigningPrefix(), nil, true)
}

func MultiSigningHash(s MultiSignable, account Account) (Hash256, []byte, error) {
return raw(s, s.MultiSigningPrefix(), account.Bytes(), true)
}

func Node(h Storer) (Hash256, []byte, error) {
Expand All @@ -30,14 +34,14 @@ func Node(h Storer) (Hash256, []byte, error) {
return zero256, nil, err
}
}
key, value, err := raw(h, h.Prefix(), true)
key, value, err := raw(h, h.Prefix(), nil, true)
if err != nil {
return zero256, nil, err
}
return key, append(header.Bytes(), value...), nil
}

func raw(value interface{}, prefix HashPrefix, ignoreSigningFields bool) (Hash256, []byte, error) {
func raw(value interface{}, prefix HashPrefix, suffix []byte, ignoreSigningFields bool) (Hash256, []byte, error) {
buf := new(bytes.Buffer)
hasher := sha512.New()
multi := io.MultiWriter(buf, hasher)
Expand All @@ -47,6 +51,9 @@ func raw(value interface{}, prefix HashPrefix, ignoreSigningFields bool) (Hash25
if err := writeRaw(multi, value, ignoreSigningFields); err != nil {
return zero256, nil, err
}
if err := write(hasher, suffix); err != nil {
return zero256, nil, err
}
var hash Hash256
copy(hash[:], hasher.Sum(nil))
return hash, buf.Bytes(), nil
Expand Down
17 changes: 9 additions & 8 deletions data/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ type LedgerNamespace uint16

const (
// Hash Prefixes
HP_TRANSACTION_ID HashPrefix = 0x54584E00 // 'TXN' transaction
HP_TRANSACTION_NODE HashPrefix = 0x534E4400 // 'SND' transaction plus metadata (probably should have been TND!)
HP_LEAF_NODE HashPrefix = 0x4D4C4E00 // 'MLN' account state
HP_INNER_NODE HashPrefix = 0x4D494E00 // 'MIN' inner node in tree
HP_LEDGER_MASTER HashPrefix = 0x4C575200 // 'LWR' ledger master data for signing (probably should have been LGR!)
HP_TRANSACTION_SIGN HashPrefix = 0x53545800 // 'STX' inner transaction to sign
HP_VALIDATION HashPrefix = 0x56414C00 // 'VAL' validation for signing
HP_PROPOSAL HashPrefix = 0x50525000 // 'PRP' proposal for signing
HP_TRANSACTION_ID HashPrefix = 0x54584E00 // 'TXN' transaction
HP_TRANSACTION_NODE HashPrefix = 0x534E4400 // 'SND' transaction plus metadata (probably should have been TND!)
HP_LEAF_NODE HashPrefix = 0x4D4C4E00 // 'MLN' account state
HP_INNER_NODE HashPrefix = 0x4D494E00 // 'MIN' inner node in tree
HP_LEDGER_MASTER HashPrefix = 0x4C575200 // 'LWR' ledger master data for signing (probably should have been LGR!)
HP_TRANSACTION_SIGN HashPrefix = 0x53545800 // 'STX' inner transaction to sign
HP_TRANSACTION_MULTISIGN HashPrefix = 0x534D5400 // 'SMT' inner transaction to multi-sign
HP_VALIDATION HashPrefix = 0x56414C00 // 'VAL' validation for signing
HP_PROPOSAL HashPrefix = 0x50525000 // 'PRP' proposal for signing

// Node Types
NT_UNKNOWN NodeType = 0
Expand Down
9 changes: 9 additions & 0 deletions data/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ type Signable interface {
GetSignature() *VariableLength
}

type MultiSignable interface {
Hashable
InitialiseForSigning()
MultiSigningPrefix() HashPrefix
GetPublicKey() *PublicKey
GetSignature() *VariableLength
SetSigners([]Signer)
}

type Router interface {
Hashable
SuppressionId() Hash256
Expand Down
8 changes: 6 additions & 2 deletions data/ledgerentry.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,16 @@ type Escrow struct {
DestinationNode *NodeIndex `json:",omitempty"`
}

type SignerEntry struct {
type SignerEntryItem struct {
Account *Account `json:",omitempty"`
SignerWeight *uint16 `json:",omitempty"`
WalletLocator *Hash256 `json:",omitempty"`
}

type SignerEntry struct {
SignerEntry SignerEntryItem
}

type SignerList struct {
leBase
Flags *LedgerEntryFlag `json:",omitempty"`
Expand Down Expand Up @@ -233,7 +237,7 @@ func (s *Escrow) Affects(account Account) bool {
}
func (s *SignerList) Affects(account Account) bool {
for _, entry := range s.SignerEntries {
if entry.Account != nil && entry.Account.Equals(account) {
if entry.SignerEntry.Account != nil && entry.SignerEntry.Account.Equals(account) {
return true
}
}
Expand Down
1 change: 1 addition & 0 deletions data/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ var resultNames = map[TransactionResult]struct {
temCANNOT_PREAUTH_SELF: {"temCANNOT_PREAUTH_SELF", "Malformed: An account may not preauthorize itself."},
temSEQ_AND_TICKET: {"temSEQ_AND_TICKET", "Transaction contains a TicketSequence and a non-zero Sequence"},
temBAD_NFTOKEN_TRANSFER_FEE: {"temBAD_NFTOKEN_TRANSFER_FEE", "Malformed: The NFToken transfer fee must be between 1 and 5000, inclusive."},
temBAD_WEIGHT: {"temBAD_WEIGHT", "The SignerListSet transaction includes a SignerWeight that is invalid, for example a zero or negative value."},

terRETRY: {"terRETRY", "Retry transaction."},
terFUNDS_SPENT: {"terFUNDS_SPENT", "Can't set password, password set funds already spent."},
Expand Down
34 changes: 33 additions & 1 deletion data/signing.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func Sign(s Signable, key crypto.Key, sequence *uint32) error {
if err != nil {
return err
}
*s.GetSignature() = VariableLength(sig)
*s.GetSignature() = sig
hash, _, err = Raw(s)
if err != nil {
return err
Expand All @@ -29,3 +29,35 @@ func CheckSignature(s Signable) (bool, error) {
}
return crypto.Verify(s.GetPublicKey().Bytes(), hash.Bytes(), msg, s.GetSignature().Bytes())
}

func MultiSign(s MultiSignable, key crypto.Key, sequence *uint32, account Account) error {
s.InitialiseForSigning()
hash, msg, err := MultiSigningHash(s, account)
if err != nil {
return err
}
//
msg = append(s.MultiSigningPrefix().Bytes(), msg...)
msg = append(msg, account.Bytes()...)

sig, err := crypto.Sign(key.Private(sequence), hash.Bytes(), msg)
if err != nil {
return err
}
*s.GetSignature() = sig
// copy pub key only after the signing
copy(s.GetPublicKey().Bytes(), key.Public(sequence))

return nil
}

func SetSigners(s MultiSignable, signers ...Signer) error {
s.SetSigners(signers)

hash, _, err := Raw(s)
if err != nil {
return err
}
copy(s.GetHash().Bytes(), hash.Bytes())
return nil
}
12 changes: 9 additions & 3 deletions data/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@ type TxBase struct {
Hash Hash256 `json:"hash"`
}

type Signer struct {
type SignerItem struct {
Account Account
TxnSignature *VariableLength
SigningPubKey *PublicKey
TxnSignature *VariableLength `json:",omitempty"`
SigningPubKey *PublicKey `json:",omitempty"`
}

type Signer struct {
Signer SignerItem
}

type Payment struct {
Expand Down Expand Up @@ -258,6 +262,8 @@ func (t *TxBase) Prefix() HashPrefix { return HP_TRANSACTION_ID
func (t *TxBase) GetPublicKey() *PublicKey { return t.SigningPubKey }
func (t *TxBase) GetSignature() *VariableLength { return t.TxnSignature }
func (t *TxBase) SigningPrefix() HashPrefix { return HP_TRANSACTION_SIGN }
func (t *TxBase) MultiSigningPrefix() HashPrefix { return HP_TRANSACTION_MULTISIGN }
func (t *TxBase) SetSigners(signers []Signer) { t.Signers = signers }
func (t *TxBase) PathSet() PathSet { return PathSet(nil) }
func (t *TxBase) GetHash() *Hash256 { return &t.Hash }

Expand Down
8 changes: 2 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ github.com/bits-and-blooms/bitset v1.2.1 h1:M+/hrU9xlMp7t4TyTDQW97d3tRPVuKFC6zBE
github.com/bits-and-blooms/bitset v1.2.1/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE=
github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 h1:MSskdM4/xJYcFzy0altH/C/xHopifpWzHUi1JeVI34Q=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
Expand Down Expand Up @@ -71,21 +71,17 @@ golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20160105164936-4f90aeace3a2/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down

0 comments on commit c77e440

Please sign in to comment.