From 58707c2b1ec2bf730933f36524cc142f1795261f Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 31 Aug 2022 10:53:49 +0300 Subject: [PATCH] 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. --- pkg/smartcontract/context/context.go | 11 ++++-- pkg/smartcontract/context/context_test.go | 46 +++++++++++++++-------- 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/pkg/smartcontract/context/context.go b/pkg/smartcontract/context/context.go index fd768604d..cd4d09d0e 100644 --- a/pkg/smartcontract/context/context.go +++ b/pkg/smartcontract/context/context.go @@ -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") } item.AddSignature(pub, sig) - if len(item.Signatures) == len(ctr.Parameters) { + if len(item.Signatures) >= len(ctr.Parameters) { indexMap := map[string]int{} for i := range pubs { 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 { - 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 { return sigs[i].index < sigs[j].index diff --git a/pkg/smartcontract/context/context_test.go b/pkg/smartcontract/context/context_test.go index 0b73c5718..c873b63e8 100644 --- a/pkg/smartcontract/context/context_test.go +++ b/pkg/smartcontract/context/context_test.go @@ -96,24 +96,38 @@ func TestParameterContext_AddSignatureMultisig(t *testing.T) { sig := priv.SignHashable(uint32(c.Network), tx) require.Error(t, c.AddSignature(ctr.ScriptHash(), ctr, priv.PublicKey(), sig)) - indices := []int{2, 3, 0} // random order - for _, i := range indices { - sig := privs[i].SignHashable(uint32(c.Network), tx) - require.NoError(t, c.AddSignature(ctr.ScriptHash(), ctr, pubs[i], sig)) - require.Error(t, c.AddSignature(ctr.ScriptHash(), ctr, pubs[i], sig)) + indices := []int{2, 3, 0, 1} // random order + testSigWit := func(t *testing.T, num int) { + for _, i := range indices[:num] { + sig := privs[i].SignHashable(uint32(c.Network), tx) + 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()] - require.NotNil(t, item) - require.Equal(t, sig, item.GetSignature(pubs[i])) + item := c.Items[ctr.ScriptHash()] + require.NotNil(t, item) + 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("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) { + testSigWit(t, 3) + }) + t.Run("larger number of sigs", func(t *testing.T) { + // Clean up. + var itm = c.Items[ctr.ScriptHash()] + for i := range itm.Parameters { + itm.Parameters[i].Value = nil + } + itm.Signatures = make(map[string][]byte) + testSigWit(t, 4) }) }