parent
158f0d9d9c
commit
dd05cae506
2 changed files with 56 additions and 2 deletions
|
@ -1380,6 +1380,7 @@ var (
|
||||||
ErrTxSmallNetworkFee = errors.New("too small network fee")
|
ErrTxSmallNetworkFee = errors.New("too small network fee")
|
||||||
ErrTxTooBig = errors.New("too big transaction")
|
ErrTxTooBig = errors.New("too big transaction")
|
||||||
ErrMemPoolConflict = errors.New("invalid transaction due to conflicts with the memory pool")
|
ErrMemPoolConflict = errors.New("invalid transaction due to conflicts with the memory pool")
|
||||||
|
ErrInvalidScript = errors.New("invalid script")
|
||||||
ErrTxInvalidWitnessNum = errors.New("number of signers doesn't match witnesses")
|
ErrTxInvalidWitnessNum = errors.New("number of signers doesn't match witnesses")
|
||||||
ErrInvalidAttribute = errors.New("invalid attribute")
|
ErrInvalidAttribute = errors.New("invalid attribute")
|
||||||
)
|
)
|
||||||
|
@ -1387,6 +1388,13 @@ var (
|
||||||
// verifyAndPoolTx verifies whether a transaction is bonafide or not and tries
|
// verifyAndPoolTx verifies whether a transaction is bonafide or not and tries
|
||||||
// to add it to the mempool given.
|
// to add it to the mempool given.
|
||||||
func (bc *Blockchain) verifyAndPoolTx(t *transaction.Transaction, pool *mempool.Pool, feer mempool.Feer, data ...interface{}) error {
|
func (bc *Blockchain) verifyAndPoolTx(t *transaction.Transaction, pool *mempool.Pool, feer mempool.Feer, data ...interface{}) error {
|
||||||
|
// This code can technically be moved out of here, because it doesn't
|
||||||
|
// really require a chain lock.
|
||||||
|
err := vm.IsScriptCorrect(t.Script, nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%w: %v", ErrInvalidScript, err)
|
||||||
|
}
|
||||||
|
|
||||||
height := bc.BlockHeight()
|
height := bc.BlockHeight()
|
||||||
isPartialTx := data != nil
|
isPartialTx := data != nil
|
||||||
if t.ValidUntilBlock <= height || !isPartialTx && t.ValidUntilBlock > height+transaction.MaxValidUntilBlockIncrement {
|
if t.ValidUntilBlock <= height || !isPartialTx && t.ValidUntilBlock > height+transaction.MaxValidUntilBlockIncrement {
|
||||||
|
@ -1424,7 +1432,7 @@ func (bc *Blockchain) verifyAndPoolTx(t *transaction.Transaction, pool *mempool.
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := bc.verifyTxWitnesses(t, nil, isPartialTx)
|
err = bc.verifyTxWitnesses(t, nil, isPartialTx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1728,7 +1736,9 @@ var (
|
||||||
ErrWitnessHashMismatch = errors.New("witness hash mismatch")
|
ErrWitnessHashMismatch = errors.New("witness hash mismatch")
|
||||||
ErrNativeContractWitness = errors.New("native contract witness must have empty verification script")
|
ErrNativeContractWitness = errors.New("native contract witness must have empty verification script")
|
||||||
ErrVerificationFailed = errors.New("signature check failed")
|
ErrVerificationFailed = errors.New("signature check failed")
|
||||||
|
ErrInvalidInvocation = errors.New("invalid invocation script")
|
||||||
ErrInvalidSignature = fmt.Errorf("%w: invalid signature", ErrVerificationFailed)
|
ErrInvalidSignature = fmt.Errorf("%w: invalid signature", ErrVerificationFailed)
|
||||||
|
ErrInvalidVerification = errors.New("invalid verification script")
|
||||||
ErrUnknownVerificationContract = errors.New("unknown verification contract")
|
ErrUnknownVerificationContract = errors.New("unknown verification contract")
|
||||||
ErrInvalidVerificationContract = errors.New("verification contract is missing `verify` method")
|
ErrInvalidVerificationContract = errors.New("verification contract is missing `verify` method")
|
||||||
)
|
)
|
||||||
|
@ -1744,6 +1754,10 @@ func (bc *Blockchain) initVerificationVM(ic *interop.Context, hash util.Uint160,
|
||||||
if bc.contracts.ByHash(hash) != nil {
|
if bc.contracts.ByHash(hash) != nil {
|
||||||
return ErrNativeContractWitness
|
return ErrNativeContractWitness
|
||||||
}
|
}
|
||||||
|
err := vm.IsScriptCorrect(witness.VerificationScript, nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%w: %v", ErrInvalidVerification, err)
|
||||||
|
}
|
||||||
v.LoadScriptWithFlags(witness.VerificationScript, callflag.ReadStates)
|
v.LoadScriptWithFlags(witness.VerificationScript, callflag.ReadStates)
|
||||||
} else {
|
} else {
|
||||||
cs, err := ic.GetContract(hash)
|
cs, err := ic.GetContract(hash)
|
||||||
|
@ -1765,6 +1779,10 @@ func (bc *Blockchain) initVerificationVM(ic *interop.Context, hash util.Uint160,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(witness.InvocationScript) != 0 {
|
if len(witness.InvocationScript) != 0 {
|
||||||
|
err := vm.IsScriptCorrect(witness.InvocationScript, nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%w: %v", ErrInvalidInvocation, err)
|
||||||
|
}
|
||||||
v.LoadScript(witness.InvocationScript)
|
v.LoadScript(witness.InvocationScript)
|
||||||
if isNative {
|
if isNative {
|
||||||
if err := v.StepOut(); err != nil {
|
if err := v.StepOut(); err != nil {
|
||||||
|
|
|
@ -390,6 +390,42 @@ func TestVerifyTx(t *testing.T) {
|
||||||
require.Equal(t, expectedNetFee, bc.FeePerByte()*int64(actualSize)+gasConsumed)
|
require.Equal(t, expectedNetFee, bc.FeePerByte()*int64(actualSize)+gasConsumed)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
t.Run("InvalidTxScript", func(t *testing.T) {
|
||||||
|
tx := bc.newTestTx(h, testScript)
|
||||||
|
tx.Script = append(tx.Script, 0xff)
|
||||||
|
require.NoError(t, accs[0].SignTx(tx))
|
||||||
|
checkErr(t, ErrInvalidScript, tx)
|
||||||
|
})
|
||||||
|
t.Run("InvalidVerificationScript", func(t *testing.T) {
|
||||||
|
tx := bc.newTestTx(h, testScript)
|
||||||
|
verif := []byte{byte(opcode.JMP), 3, 0xff, byte(opcode.PUSHT)}
|
||||||
|
tx.Signers = append(tx.Signers, transaction.Signer{
|
||||||
|
Account: hash.Hash160(verif),
|
||||||
|
Scopes: transaction.Global,
|
||||||
|
})
|
||||||
|
tx.NetworkFee += 1000000
|
||||||
|
require.NoError(t, accs[0].SignTx(tx))
|
||||||
|
tx.Scripts = append(tx.Scripts, transaction.Witness{
|
||||||
|
InvocationScript: []byte{},
|
||||||
|
VerificationScript: verif,
|
||||||
|
})
|
||||||
|
checkErr(t, ErrInvalidVerification, tx)
|
||||||
|
})
|
||||||
|
t.Run("InvalidInvocationScript", func(t *testing.T) {
|
||||||
|
tx := bc.newTestTx(h, testScript)
|
||||||
|
verif := []byte{byte(opcode.PUSHT)}
|
||||||
|
tx.Signers = append(tx.Signers, transaction.Signer{
|
||||||
|
Account: hash.Hash160(verif),
|
||||||
|
Scopes: transaction.Global,
|
||||||
|
})
|
||||||
|
tx.NetworkFee += 1000000
|
||||||
|
require.NoError(t, accs[0].SignTx(tx))
|
||||||
|
tx.Scripts = append(tx.Scripts, transaction.Witness{
|
||||||
|
InvocationScript: []byte{byte(opcode.JMP), 3, 0xff},
|
||||||
|
VerificationScript: verif,
|
||||||
|
})
|
||||||
|
checkErr(t, ErrInvalidInvocation, tx)
|
||||||
|
})
|
||||||
t.Run("Conflict", func(t *testing.T) {
|
t.Run("Conflict", func(t *testing.T) {
|
||||||
balance := bc.GetUtilityTokenBalance(h).Int64()
|
balance := bc.GetUtilityTokenBalance(h).Int64()
|
||||||
tx := bc.newTestTx(h, testScript)
|
tx := bc.newTestTx(h, testScript)
|
||||||
|
@ -583,7 +619,7 @@ func TestVerifyTx(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("InvalidScript", func(t *testing.T) {
|
t.Run("InvalidScript", func(t *testing.T) {
|
||||||
tx := getOracleTx(t)
|
tx := getOracleTx(t)
|
||||||
tx.Script[0] = ^tx.Script[0]
|
tx.Script = append(tx.Script, byte(opcode.NOP))
|
||||||
require.NoError(t, oracleAcc.SignTx(tx))
|
require.NoError(t, oracleAcc.SignTx(tx))
|
||||||
checkErr(t, ErrInvalidAttribute, tx)
|
checkErr(t, ErrInvalidAttribute, tx)
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue