vm: zero GAS means no GAS, use fee data to properly limit execution
We were accepting transactions with zero system fee, but we shouldn't do that. Also, transaction's verification execution has to be limited by network fee.
This commit is contained in:
parent
a5d6c76928
commit
db027ad9c5
10 changed files with 28 additions and 19 deletions
|
@ -24,7 +24,7 @@ import (
|
|||
|
||||
func TestNewService(t *testing.T) {
|
||||
srv := newTestService(t)
|
||||
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
|
||||
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 100000)
|
||||
tx.ValidUntilBlock = 1
|
||||
addSender(t, tx)
|
||||
signTx(t, srv.Chain.FeePerByte(), tx)
|
||||
|
@ -42,7 +42,7 @@ func TestService_GetVerified(t *testing.T) {
|
|||
srv.dbft.Start()
|
||||
var txs []*transaction.Transaction
|
||||
for i := 0; i < 4; i++ {
|
||||
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
|
||||
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 100000)
|
||||
tx.Nonce = 123 + uint32(i)
|
||||
tx.ValidUntilBlock = 1
|
||||
txs = append(txs, tx)
|
||||
|
|
|
@ -568,6 +568,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
|
|||
if block.Index > 0 {
|
||||
systemInterop := bc.newInteropContext(trigger.System, cache, block, nil)
|
||||
v := SpawnVM(systemInterop)
|
||||
v.GasLimit = -1
|
||||
v.LoadScriptWithFlags(bc.contracts.GetPersistScript(), smartcontract.AllowModifyStates|smartcontract.AllowCall)
|
||||
v.SetPriceGetter(getPrice)
|
||||
if err := v.Run(); err != nil {
|
||||
|
@ -1358,7 +1359,7 @@ func (bc *Blockchain) verifyTxWitnesses(t *transaction.Transaction, block *block
|
|||
sort.Slice(witnesses, func(i, j int) bool { return witnesses[i].ScriptHash().Less(witnesses[j].ScriptHash()) })
|
||||
interopCtx := bc.newInteropContext(trigger.Verification, bc.dao, block, t)
|
||||
for i := 0; i < len(hashes); i++ {
|
||||
err := bc.verifyHashAgainstScript(hashes[i], &witnesses[i], interopCtx, false, 0)
|
||||
err := bc.verifyHashAgainstScript(hashes[i], &witnesses[i], interopCtx, false, t.NetworkFee)
|
||||
if err != nil {
|
||||
numStr := fmt.Sprintf("witness #%d", i)
|
||||
return errors.Wrap(err, numStr)
|
||||
|
|
|
@ -257,7 +257,7 @@ func TestCreateBasicChain(t *testing.T) {
|
|||
script = io.NewBufBinWriter()
|
||||
emit.AppCallWithOperationAndArgs(script.BinWriter, hash.Hash160(avm), "Put", "testkey", "testvalue")
|
||||
|
||||
txInv := transaction.New(testchain.Network(), script.Bytes(), 0)
|
||||
txInv := transaction.New(testchain.Network(), script.Bytes(), 1*native.GASFactor)
|
||||
txInv.Nonce = getNextNonce()
|
||||
txInv.ValidUntilBlock = validUntilBlock
|
||||
txInv.Sender = priv0ScriptHash
|
||||
|
@ -288,7 +288,7 @@ func TestCreateBasicChain(t *testing.T) {
|
|||
sh := hash.Hash160(avm)
|
||||
w := io.NewBufBinWriter()
|
||||
emit.AppCallWithOperationAndArgs(w.BinWriter, sh, "init")
|
||||
initTx := transaction.New(testchain.Network(), w.Bytes(), 0)
|
||||
initTx := transaction.New(testchain.Network(), w.Bytes(), 1*native.GASFactor)
|
||||
initTx.Nonce = getNextNonce()
|
||||
initTx.ValidUntilBlock = validUntilBlock
|
||||
initTx.Sender = priv0ScriptHash
|
||||
|
@ -378,7 +378,7 @@ func newNEP5Transfer(sc, from, to util.Uint160, amount int64) *transaction.Trans
|
|||
emit.Opcode(w.BinWriter, opcode.ASSERT)
|
||||
|
||||
script := w.Bytes()
|
||||
return transaction.New(testchain.Network(), script, 0)
|
||||
return transaction.New(testchain.Network(), script, 10000000)
|
||||
}
|
||||
|
||||
func addSender(txs ...*transaction.Transaction) error {
|
||||
|
|
|
@ -60,6 +60,7 @@ func initCHECKMULTISIGVM(t *testing.T, n int, ik, is []int) *vm.VM {
|
|||
binary.LittleEndian.PutUint32(buf[1:], ecdsaCheckMultisigID)
|
||||
|
||||
v := vm.New()
|
||||
v.GasLimit = -1
|
||||
ic := &interop.Context{Trigger: trigger.Verification}
|
||||
v.RegisterInteropGetter(GetInterop(ic))
|
||||
v.LoadScript(buf)
|
||||
|
|
|
@ -227,7 +227,7 @@ func invokeNativePolicyMethod(chain *Blockchain, method string, args ...interfac
|
|||
return nil, w.Err
|
||||
}
|
||||
script := w.Bytes()
|
||||
tx := transaction.New(chain.GetConfig().Magic, script, 0)
|
||||
tx := transaction.New(chain.GetConfig().Magic, script, 10000000)
|
||||
validUntil := chain.blockHeight + 1
|
||||
tx.ValidUntilBlock = validUntil
|
||||
err := addSender(tx)
|
||||
|
|
|
@ -52,7 +52,7 @@ type rpcTestCase struct {
|
|||
}
|
||||
|
||||
const testContractHash = "10e262ef80c76bdecca287a2c047841fc02c3129"
|
||||
const deploymentTxHash = "ad8b149c799d4b2337162b0ad23e0ba8845cddb9cfca8a45587ee207015d2a7c"
|
||||
const deploymentTxHash = "4843700d16be3e6507a25909d3b2aa1472dcd0526be2520f2bfdd53d768bfebf"
|
||||
|
||||
var rpcTestCases = map[string][]rpcTestCase{
|
||||
"getapplicationlog": {
|
||||
|
@ -148,7 +148,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
|||
},
|
||||
{
|
||||
Asset: e.chain.UtilityTokenHash(),
|
||||
Amount: "918.01738700",
|
||||
Amount: "915.79002700",
|
||||
LastUpdated: 6,
|
||||
}},
|
||||
Address: testchain.PrivateKeyByID(0).GetScriptHash().StringLE(),
|
||||
|
@ -720,7 +720,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
|||
"sendrawtransaction": {
|
||||
{
|
||||
name: "positive",
|
||||
params: `["000a000000316e851039019d39dfc2c37d6c3fee19fd5809870000000000000000f2ad050000000000b00400000001316e851039019d39dfc2c37d6c3fee19fd580987015d0300e87648170000000c1420728274afafc36f43a071d328cfa3e629d9cbb00c14316e851039019d39dfc2c37d6c3fee19fd58098713c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b523801420c409803db41e66a94e0bd6fdd3d7a7b1e106c1e2281c9782a231f32df036bb80c7f19155cdb9a52a45cf8d93ec9c1e8df69d6ee35625f352d1710c7cc6eee26003c290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"]`,
|
||||
params: `["000a000000316e851039019d39dfc2c37d6c3fee19fd58098780969800000000009269130000000000b00400000001316e851039019d39dfc2c37d6c3fee19fd580987015d0300e87648170000000c1420728274afafc36f43a071d328cfa3e629d9cbb00c14316e851039019d39dfc2c37d6c3fee19fd58098713c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b523801420c4037c8c002c3352329c5f2995567a355d57372447c156ea544844d5f8027babf4cd86142d986681992805e3f62f2625b551f18cf05897e6ea7c135f22537bb740e290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"]`,
|
||||
result: func(e *executor) interface{} {
|
||||
v := true
|
||||
return &v
|
||||
|
|
BIN
pkg/rpc/server/testdata/testblocks.acc
vendored
BIN
pkg/rpc/server/testdata/testblocks.acc
vendored
Binary file not shown.
|
@ -111,6 +111,7 @@ func TestParameterContext_AddSignatureMultisig(t *testing.T) {
|
|||
|
||||
func newTestVM(w *transaction.Witness, tx *transaction.Transaction) *vm.VM {
|
||||
v := vm.New()
|
||||
v.GasLimit = -1
|
||||
v.RegisterInteropGetter(crypto.GetInterop(&interop.Context{Container: tx}))
|
||||
v.LoadScript(w.VerificationScript)
|
||||
v.LoadScript(w.InvocationScript)
|
||||
|
|
|
@ -133,7 +133,7 @@ func (v *VM) GasConsumed() int64 {
|
|||
// AddGas consumes specified amount of gas. It returns true iff gas limit wasn't exceeded.
|
||||
func (v *VM) AddGas(gas int64) bool {
|
||||
v.gasConsumed += gas
|
||||
return v.GasLimit == 0 || v.gasConsumed <= v.GasLimit
|
||||
return v.GasLimit < 0 || v.gasConsumed <= v.GasLimit
|
||||
}
|
||||
|
||||
// Estack returns the evaluation stack so interop hooks can utilize this.
|
||||
|
@ -523,7 +523,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
|||
|
||||
if v.getPrice != nil && ctx.ip < len(ctx.prog) {
|
||||
v.gasConsumed += v.getPrice(v, op, parameter)
|
||||
if v.GasLimit > 0 && v.gasConsumed > v.GasLimit {
|
||||
if v.GasLimit >= 0 && v.gasConsumed > v.GasLimit {
|
||||
panic("gas limit is exceeded")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ func fooInteropGetter(id uint32) *InteropFuncPrice {
|
|||
}
|
||||
|
||||
func TestInteropHook(t *testing.T) {
|
||||
v := New()
|
||||
v := newTestVM()
|
||||
v.RegisterInteropGetter(fooInteropGetter)
|
||||
|
||||
buf := io.NewBufBinWriter()
|
||||
|
@ -48,14 +48,14 @@ func TestInteropHook(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRegisterInteropGetter(t *testing.T) {
|
||||
v := New()
|
||||
v := newTestVM()
|
||||
currRegistered := len(v.getInterop)
|
||||
v.RegisterInteropGetter(fooInteropGetter)
|
||||
assert.Equal(t, currRegistered+1, len(v.getInterop))
|
||||
}
|
||||
|
||||
func TestVM_SetPriceGetter(t *testing.T) {
|
||||
v := New()
|
||||
v := newTestVM()
|
||||
prog := []byte{
|
||||
byte(opcode.PUSH4), byte(opcode.PUSH2),
|
||||
byte(opcode.PUSHDATA1), 0x01, 0x01,
|
||||
|
@ -103,7 +103,7 @@ func TestVM_SetPriceGetter(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAddGas(t *testing.T) {
|
||||
v := New()
|
||||
v := newTestVM()
|
||||
v.GasLimit = 10
|
||||
require.True(t, v.AddGas(5))
|
||||
require.True(t, v.AddGas(5))
|
||||
|
@ -111,7 +111,7 @@ func TestAddGas(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBytesToPublicKey(t *testing.T) {
|
||||
v := New()
|
||||
v := newTestVM()
|
||||
cache := v.GetPublicKeys()
|
||||
assert.Equal(t, 0, len(cache))
|
||||
keyHex := "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c"
|
||||
|
@ -819,7 +819,7 @@ func TestSerializeInterop(t *testing.T) {
|
|||
func getTestCallFlagsFunc(syscall []byte, flags smartcontract.CallFlag, result interface{}) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
script := append([]byte{byte(opcode.SYSCALL)}, syscall...)
|
||||
v := New()
|
||||
v := newTestVM()
|
||||
v.RegisterInteropGetter(getTestingInterop)
|
||||
v.LoadScriptWithFlags(script, flags)
|
||||
if result == nil {
|
||||
|
@ -2518,7 +2518,7 @@ func makeProgram(opcodes ...opcode.Opcode) []byte {
|
|||
}
|
||||
|
||||
func load(prog []byte) *VM {
|
||||
vm := New()
|
||||
vm := newTestVM()
|
||||
if len(prog) != 0 {
|
||||
vm.LoadScript(prog)
|
||||
}
|
||||
|
@ -2533,3 +2533,9 @@ func randomBytes(n int) []byte {
|
|||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func newTestVM() *VM {
|
||||
v := New()
|
||||
v.GasLimit = -1
|
||||
return v
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue