context: handle the case when we have more sigs than needed

We can technically have more signatures in the file than we need and it's OK,
this case should be handled.
This commit is contained in:
Roman Khimov 2022-08-31 10:53:49 +03:00
parent 4b136e8ab1
commit 58707c2b1e
2 changed files with 38 additions and 19 deletions

View file

@ -96,14 +96,19 @@ func (c *ParameterContext) AddSignature(h util.Uint160, ctr *wallet.Contract, pu
return errors.New("public key is not present in script") return errors.New("public key is not present in script")
} }
item.AddSignature(pub, sig) item.AddSignature(pub, sig)
if len(item.Signatures) == len(ctr.Parameters) { if len(item.Signatures) >= len(ctr.Parameters) {
indexMap := map[string]int{} indexMap := map[string]int{}
for i := range pubs { for i := range pubs {
indexMap[hex.EncodeToString(pubs[i])] = i indexMap[hex.EncodeToString(pubs[i])] = i
} }
sigs := make([]sigWithIndex, 0, len(item.Signatures)) sigs := make([]sigWithIndex, len(item.Parameters))
var i int
for pub, sig := range item.Signatures { for pub, sig := range item.Signatures {
sigs = append(sigs, sigWithIndex{index: indexMap[pub], sig: sig}) sigs[i] = sigWithIndex{index: indexMap[pub], sig: sig}
i++
if i == len(sigs) {
break
}
} }
sort.Slice(sigs, func(i, j int) bool { sort.Slice(sigs, func(i, j int) bool {
return sigs[i].index < sigs[j].index return sigs[i].index < sigs[j].index

View file

@ -96,24 +96,38 @@ func TestParameterContext_AddSignatureMultisig(t *testing.T) {
sig := priv.SignHashable(uint32(c.Network), tx) sig := priv.SignHashable(uint32(c.Network), tx)
require.Error(t, c.AddSignature(ctr.ScriptHash(), ctr, priv.PublicKey(), sig)) require.Error(t, c.AddSignature(ctr.ScriptHash(), ctr, priv.PublicKey(), sig))
indices := []int{2, 3, 0} // random order indices := []int{2, 3, 0, 1} // random order
for _, i := range indices { testSigWit := func(t *testing.T, num int) {
sig := privs[i].SignHashable(uint32(c.Network), tx) for _, i := range indices[:num] {
require.NoError(t, c.AddSignature(ctr.ScriptHash(), ctr, pubs[i], sig)) sig := privs[i].SignHashable(uint32(c.Network), tx)
require.Error(t, c.AddSignature(ctr.ScriptHash(), ctr, pubs[i], sig)) require.NoError(t, c.AddSignature(ctr.ScriptHash(), ctr, pubs[i], sig))
require.Error(t, c.AddSignature(ctr.ScriptHash(), ctr, pubs[i], sig))
item := c.Items[ctr.ScriptHash()] item := c.Items[ctr.ScriptHash()]
require.NotNil(t, item) require.NotNil(t, item)
require.Equal(t, sig, item.GetSignature(pubs[i])) require.Equal(t, sig, item.GetSignature(pubs[i]))
}
t.Run("GetWitness", func(t *testing.T) {
w, err := c.GetWitness(ctr.ScriptHash())
require.NoError(t, err)
v := newTestVM(w, tx)
require.NoError(t, v.Run())
require.Equal(t, 1, v.Estack().Len())
require.Equal(t, true, v.Estack().Pop().Value())
})
} }
t.Run("exact number of sigs", func(t *testing.T) {
t.Run("GetWitness", func(t *testing.T) { testSigWit(t, 3)
w, err := c.GetWitness(ctr.ScriptHash()) })
require.NoError(t, err) t.Run("larger number of sigs", func(t *testing.T) {
v := newTestVM(w, tx) // Clean up.
require.NoError(t, v.Run()) var itm = c.Items[ctr.ScriptHash()]
require.Equal(t, 1, v.Estack().Len()) for i := range itm.Parameters {
require.Equal(t, true, v.Estack().Pop().Value()) itm.Parameters[i].Value = nil
}
itm.Signatures = make(map[string][]byte)
testSigWit(t, 4)
}) })
} }