mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2025-01-23 23:24:37 +00:00
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"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"sort"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"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).
|
// 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
|
// 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 {
|
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) {
|
if len(hashes) != len(witnesses) {
|
||||||
return errors.Errorf("expected len(hashes) == len(witnesses). got: %d != %d", 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++ {
|
for i := 0; i < len(hashes); i++ {
|
||||||
verification := witnesses[i].VerificationScript
|
verification := witnesses[i].VerificationScript
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,18 @@ func (u Uint160) Equals(other Uint160) bool {
|
||||||
return u == other
|
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.
|
// UnmarshalJSON implements the json unmarshaller interface.
|
||||||
func (u *Uint160) UnmarshalJSON(data []byte) (err error) {
|
func (u *Uint160) UnmarshalJSON(data []byte) (err error) {
|
||||||
var js string
|
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) {
|
func TestUInt160String(t *testing.T) {
|
||||||
hexStr := "b28427088a3729b2536d10122960394e8be6721f"
|
hexStr := "b28427088a3729b2536d10122960394e8be6721f"
|
||||||
hexRevStr := "1f72e68b4e39602912106d53b229378a082784b2"
|
hexRevStr := "1f72e68b4e39602912106d53b229378a082784b2"
|
||||||
|
|
Loading…
Reference in a new issue