-
Notifications
You must be signed in to change notification settings - Fork 209
/
multisig.go
59 lines (51 loc) · 1.52 KB
/
multisig.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package multisig
import (
"fmt"
"github.com/oasisprotocol/curve25519-voi/primitives/ed25519"
"github.com/spacemeshos/go-scale"
"github.com/spacemeshos/go-spacemesh/genvm/core"
)
//go:generate scalegen
// MultiSig K/N template.
type MultiSig struct {
k uint8
PublicKeys []core.PublicKey `scale:"max=10"`
}
// MaxSpend returns amount specified in the SpendArguments.
func (ms *MultiSig) MaxSpend(method uint8, args any) (uint64, error) {
switch method {
case core.MethodSpawn:
return 0, nil
case core.MethodSpend:
return args.(*SpendArguments).Amount, nil
default:
return 0, fmt.Errorf("%w: unknown method %d", core.ErrMalformed, method)
}
}
// Verify that transaction is signed has k valid signatures.
func (ms *MultiSig) Verify(host core.Host, raw []byte, dec *scale.Decoder) bool {
sig := make(Signatures, ms.k)
n, err := scale.DecodeStructArray(dec, sig)
if err != nil {
return false
}
body := core.SigningBody(host.GetGenesisID().Bytes(), raw[:len(raw)-n])
batch := ed25519.NewBatchVerifierWithCapacity(int(ms.k))
last := uint8(0)
for i, part := range sig {
if part.Ref >= uint8(len(ms.PublicKeys)) {
return false
}
if i != 0 && part.Ref <= last {
return false
}
last = part.Ref
batch.Add(ms.PublicKeys[part.Ref][:], body, part.Sig[:])
}
verified, _ := batch.Verify(nil)
return verified
}
// Spend transfers an amount to the address specified in SpendArguments.
func (ms *MultiSig) Spend(host core.Host, args *SpendArguments) error {
return host.Transfer(args.Destination, args.Amount)
}