core: sort hashes and witnesses in VerifyWitnesses()
Fixes failure to verify some multi-witnesses transactions in Testnet chain. C# code contains similar logic.
This commit is contained in:
parent
dd0dd2d031
commit
8537700b7b
3 changed files with 33 additions and 1 deletions
|
@ -5,6 +5,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
|
@ -965,7 +966,9 @@ func (bc *Blockchain) GetScriptHashesForVerifying(t *transaction.Transaction) ([
|
|||
|
||||
}
|
||||
|
||||
// VerifyWitnesses verify the scripts (witnesses) that come with a transactions.
|
||||
// VerifyWitnesses verify the scripts (witnesses) that come with a given
|
||||
// transaction. It can reorder them by ScriptHash, because that's required to
|
||||
// match a slice of script hashes from the Blockchain.
|
||||
// Golang implementation of VerifyWitnesses method in C# (https://github.com/neo-project/neo/blob/master/neo/SmartContract/Helper.cs#L87).
|
||||
// Unfortunately the IVerifiable interface could not be implemented because we can't move the References method in blockchain.go to the transaction.go file
|
||||
func (bc *Blockchain) VerifyWitnesses(t *transaction.Transaction) error {
|
||||
|
@ -978,6 +981,8 @@ func (bc *Blockchain) VerifyWitnesses(t *transaction.Transaction) error {
|
|||
if len(hashes) != len(witnesses) {
|
||||
return errors.Errorf("expected len(hashes) == len(witnesses). got: %d != %d", len(hashes), len(witnesses))
|
||||
}
|
||||
sort.Slice(hashes, func(i, j int) bool { return hashes[i].Less(hashes[j]) })
|
||||
sort.Slice(witnesses, func(i, j int) bool { return witnesses[i].ScriptHash().Less(witnesses[j].ScriptHash()) })
|
||||
for i := 0; i < len(hashes); i++ {
|
||||
verification := witnesses[i].VerificationScript
|
||||
|
||||
|
|
|
@ -59,6 +59,18 @@ func (u Uint160) Equals(other Uint160) bool {
|
|||
return u == other
|
||||
}
|
||||
|
||||
// Less returns true if this value is less than given Uint160 value. It's
|
||||
// primarily intended to be used for sorting purposes.
|
||||
func (u Uint160) Less(other Uint160) bool {
|
||||
for k := range u {
|
||||
if u[k] == other[k] {
|
||||
continue
|
||||
}
|
||||
return u[k] < other[k]
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json unmarshaller interface.
|
||||
func (u *Uint160) UnmarshalJSON(data []byte) (err error) {
|
||||
var js string
|
||||
|
|
|
@ -76,6 +76,21 @@ func TestUInt160Equals(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestUInt160Less(t *testing.T) {
|
||||
a := "2d3b96ae1bcc5a585e075e3b81920210dec16302"
|
||||
b := "2d3b96ae1bcc5a585e075e3b81920210dec16303"
|
||||
|
||||
ua, err := Uint160DecodeString(a)
|
||||
assert.Nil(t, err)
|
||||
ua2, err := Uint160DecodeString(a)
|
||||
assert.Nil(t, err)
|
||||
ub, err := Uint160DecodeString(b)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, true, ua.Less(ub))
|
||||
assert.Equal(t, false, ua.Less(ua2))
|
||||
assert.Equal(t, false, ub.Less(ua))
|
||||
}
|
||||
|
||||
func TestUInt160String(t *testing.T) {
|
||||
hexStr := "b28427088a3729b2536d10122960394e8be6721f"
|
||||
hexRevStr := "1f72e68b4e39602912106d53b229378a082784b2"
|
||||
|
|
Loading…
Reference in a new issue