diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 863da412d..a44a03386 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -1372,21 +1372,30 @@ func (bc *Blockchain) GetTestVM() (*vm.VM, storage.Store) { return vm, tmpStore } -// verifyHashAgainstScript verifies given hash against the given witness. -func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transaction.Witness, checkedHash util.Uint256, interopCtx *interopContext, useKeys bool) error { +// ScriptFromWitness returns verification script for provided witness. +// If hash is not equal to the witness script hash, error is returned. +func ScriptFromWitness(hash util.Uint160, witness *transaction.Witness) ([]byte, error) { verification := witness.VerificationScript if len(verification) == 0 { bb := new(bytes.Buffer) err := vm.EmitAppCall(bb, hash, false) if err != nil { - return err + return nil, err } verification = bb.Bytes() - } else { - if h := witness.ScriptHash(); hash != h { - return errors.New("witness hash mismatch") - } + } else if h := witness.ScriptHash(); hash != h { + return nil, errors.New("witness hash mismatch") + } + + return verification, nil +} + +// verifyHashAgainstScript verifies given hash against the given witness. +func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transaction.Witness, checkedHash util.Uint256, interopCtx *interopContext, useKeys bool) error { + verification, err := ScriptFromWitness(hash, witness) + if err != nil { + return err } vm := bc.spawnVMWithInterops(interopCtx) @@ -1396,7 +1405,7 @@ func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transa if useKeys && bc.keyCache[hash] != nil { vm.SetPublicKeys(bc.keyCache[hash]) } - err := vm.Run() + err = vm.Run() if vm.HasFailed() { return errors.Errorf("vm failed to execute the script with error: %s", err) } diff --git a/pkg/core/blockchain_test.go b/pkg/core/blockchain_test.go index f539b865b..0fa8b3aae 100644 --- a/pkg/core/blockchain_test.go +++ b/pkg/core/blockchain_test.go @@ -4,7 +4,10 @@ import ( "testing" "github.com/CityOfZion/neo-go/pkg/core/storage" + "github.com/CityOfZion/neo-go/pkg/core/transaction" + "github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/io" + "github.com/CityOfZion/neo-go/pkg/util" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -65,6 +68,27 @@ func TestAddBlock(t *testing.T) { assert.Equal(t, lastBlock.Hash(), bc.CurrentHeaderHash()) } +func TestScriptFromWitness(t *testing.T) { + witness := &transaction.Witness{} + h := util.Uint160{1, 2, 3} + + res, err := ScriptFromWitness(h, witness) + require.NoError(t, err) + require.NotNil(t, res) + + witness.VerificationScript = []byte{4, 8, 15, 16, 23, 42} + h = hash.Hash160(witness.VerificationScript) + + res, err = ScriptFromWitness(h, witness) + require.NoError(t, err) + require.NotNil(t, res) + + h[0] = ^h[0] + res, err = ScriptFromWitness(h, witness) + require.Error(t, err) + require.Nil(t, res) +} + func TestGetHeader(t *testing.T) { bc := newTestChain(t) block := newBlock(1, newMinerTX())