Documentation
¶
Index ¶
- Constants
- Variables
- func NewPubKeyMultisigThreshold(k int, pubkeys []crypto.PubKey) crypto.PubKey
- func NewPubKeyMultisigThresholdChecked(k int, pubkeys []crypto.PubKey) (crypto.PubKey, error)
- type Multisignature
- type PubKeyMultisigThreshold
- func (pk PubKeyMultisigThreshold) Address() crypto.Address
- func (pk PubKeyMultisigThreshold) Bytes() []byte
- func (pk PubKeyMultisigThreshold) Equals(other crypto.PubKey) bool
- func (goo PubKeyMultisigThreshold) MarshalBinary2(cdc *amino.Codec, buf []byte, offset int) (int, error)
- func (goo PubKeyMultisigThreshold) SizeBinary2(cdc *amino.Codec) (int, error)
- func (pk PubKeyMultisigThreshold) String() string
- func (goo *PubKeyMultisigThreshold) UnmarshalBinary2(cdc *amino.Codec, bz []byte, anyDepth int) error
- func (pk PubKeyMultisigThreshold) ValidateStructure() error
- func (pk PubKeyMultisigThreshold) VerifyBytes(msg []byte, marshalledSig []byte) bool
Constants ¶
const MaxNestingDepth = 6
MaxNestingDepth is how many levels of threshold keys a PubKeyMultisigThreshold may contain, counting itself. A key holding only non-multisig constituents is depth 1; a multisig of multisigs is depth 2.
The bound exists because verifying a nested key costs one amino decode of the whole remaining signature blob per level, so an unbounded chain is quadratic in the size of a transaction that pays for it linearly. It is not bounded by auth's TxSigLimit either: std.CountSubKeys counts leaves, and a chain of 1-of-1 keys has exactly one however deep it runs.
6 is the deepest a key that branches at every level can nest while spending no more than TxSigLimit's 7 leaves. The deep shape that stays inside a leaf budget is the unbalanced one — each level holding one leaf and one subkey — and d such levels spend d+1 leaves and 2d+1 keys, so 7 leaves reach depth 6 at 13 keys. That is the same shape MaxTotalKeys admits, which is why the two bounds agree here: neither is the binding one for a branching key.
Anything deeper needs a level holding a single subkey, which delegates its whole threshold to that subkey and so expresses nothing the subkey did not already express. Those are reachable within MaxTotalKeys alone — a 1-of-1 chain is one key per level — which is why the depth bound is a separate check and not a consequence of the key budget.
const MaxTotalKeys = 14
MaxTotalKeys is how many keys a PubKeyMultisigThreshold may contain in total, counting itself, every threshold key nested within it, and every leaf key at the bottom.
The bound exists because validate scans each level's constituents pairwise to reject duplicates, so an unbounded key is quadratic in the size of a transaction that pays for it linearly. TxSigLimit bounds the width no better than it bounds the depth, and for the same reason: std.CountSubKeys counts leaves, and a constituent holding no keys at all contributes none however many of them are listed.
14 is twice auth's default TxSigLimit of 7, which is the most leaves a transaction may present. A key that spends all 7 on leaves and branches at every level needs at most 6 threshold keys above them, so 14 admits every branching key TxSigLimit permits.
It does not admit every degenerate one: 7 leaves each behind a 1-of-1 wrapper of its own is 15 keys, and is rejected here although it counts 7 against TxSigLimit. Wrapping a lone subkey expresses nothing that subkey did not already express, which is the same reasoning MaxNestingDepth rests on.
It is deliberately the tighter of the two bounds and can be raised later: a chain configuring TxSigLimit above 7 has to raise this with it.
Variables ¶
var Package = amino.RegisterPackage(amino.NewPackage( "github.com/gnolang/gno/tm2/pkg/crypto/multisig", "tm", amino.GetCallersDirname(), ).WithDependencies().WithTypes( PubKeyMultisigThreshold{}, "PubKeyMultisig", ))
Functions ¶
func NewPubKeyMultisigThreshold ¶
NewPubKeyMultisigThreshold returns a new PubKeyMultisigThreshold. Panics unless k and pubkeys describe a valid threshold key; see NewPubKeyMultisigThresholdChecked for the fallible form.
func NewPubKeyMultisigThresholdChecked ¶
NewPubKeyMultisigThresholdChecked is NewPubKeyMultisigThreshold, reporting an error rather than panicking.
A caller taking k or pubkeys from user input should use this one. What makes a threshold key valid has grown over time — a positive threshold, at least k constituents, no duplicates among them, and the structural bounds above — and a caller that pre-checks those conditions itself, one at a time, drifts out of sync with validate silently: the next condition added here becomes a panic on ordinary input at a call site nobody thought to revisit.
Types ¶
type Multisignature ¶
type Multisignature struct {
BitArray *bitarray.CompactBitArray
Sigs [][]byte
}
Multisignature is used to represent the signature object used in the multisigs. Sigs is a list of signatures, sorted by corresponding index.
func NewMultisig ¶
func NewMultisig(n int) *Multisignature
NewMultisig returns a new Multisignature of size n.
func (*Multisignature) AddSignature ¶
func (mSig *Multisignature) AddSignature(sig []byte, index int) error
AddSignature adds a signature to the multisig, at the corresponding index. If the signature already exists, replace it.
It reports an error rather than silently producing an unverifiable multisignature when index is not one of mSig's own slots. Verification requires exactly one signature per set bit — see Multisignature.ValidateBasic — and an index at or past the bit array's size sets no bit, so appending for it would break that equality and the result would be rejected on chain with nothing here having complained.
func (*Multisignature) AddSignatureFromPubKey ¶
func (mSig *Multisignature) AddSignatureFromPubKey(sig []byte, pubkey crypto.PubKey, keys []crypto.PubKey) error
AddSignatureFromPubKey adds a signature to the multisig, at the index in keys corresponding to the provided pubkey.
func (*Multisignature) Marshal ¶
func (mSig *Multisignature) Marshal() []byte
Marshal the multisignature with amino
func (Multisignature) ValidateBasic ¶
func (mSig Multisignature) ValidateBasic(nKeys int) error
ValidateBasic returns an error unless mSig is a well-formed multisignature for a threshold key over nKeys constituents.
Both places that walk a multisignature call this before trusting its shape: PubKeyMultisigThreshold.VerifyBytes and auth's signature gas consumer, which recurses over the constituent keys itself and so reaches them before VerifyBytes is called. Sharing one implementation is the point — the two must not disagree about which shapes are walkable, and the equality below is a consensus rule.
type PubKeyMultisigThreshold ¶
type PubKeyMultisigThreshold struct {
K uint `json:"threshold"`
PubKeys []crypto.PubKey `json:"pubkeys"`
}
PubKeyMultisigThreshold implements a K of N threshold multisig.
func (PubKeyMultisigThreshold) Address ¶
func (pk PubKeyMultisigThreshold) Address() crypto.Address
Address returns tmhash(PubKeyMultisigThreshold.Bytes())
func (PubKeyMultisigThreshold) Bytes ¶
func (pk PubKeyMultisigThreshold) Bytes() []byte
Bytes returns the amino encoded version of the PubKeyMultisigThreshold
func (PubKeyMultisigThreshold) Equals ¶
func (pk PubKeyMultisigThreshold) Equals(other crypto.PubKey) bool
Equals returns true iff pk and other both have the same number of keys, and all constituent keys are the same, and in the same order.
func (PubKeyMultisigThreshold) MarshalBinary2 ¶
func (PubKeyMultisigThreshold) SizeBinary2 ¶
func (goo PubKeyMultisigThreshold) SizeBinary2(cdc *amino.Codec) (int, error)
func (PubKeyMultisigThreshold) String ¶
func (pk PubKeyMultisigThreshold) String() string
func (*PubKeyMultisigThreshold) UnmarshalBinary2 ¶
func (PubKeyMultisigThreshold) ValidateStructure ¶
func (pk PubKeyMultisigThreshold) ValidateStructure() error
ValidateStructure returns an error if pk nests threshold keys more than MaxNestingDepth levels deep, or holds more than MaxTotalKeys keys in total.
It is separate from validate because auth's signature gas consumer recurses over the constituent keys itself, before VerifyBytes is ever reached, and so has to establish the same bounds on its own recursion. Both callers agreeing on one implementation is the point: these bounds are what keep that recursion, the amino decode it performs at each level, and validate's own duplicate scan linear in the transaction.
func (PubKeyMultisigThreshold) VerifyBytes ¶
func (pk PubKeyMultisigThreshold) VerifyBytes(msg []byte, marshalledSig []byte) bool
VerifyBytes expects sig to be an amino encoded version of a MultiSignature. Returns true iff the multisignature contains k or more signatures for the correct corresponding keys, and all signatures are valid. (Not just k of the signatures) The multisig uses a bitarray, so multiple signatures for the same key is not a concern.