Merge pull request #1177 from nspcc-dev/no-free-vm-runs
No free VM runs
This commit is contained in:
commit
dafb9eea4d
21 changed files with 52 additions and 31 deletions
|
@ -460,7 +460,7 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
|
|||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("bad script returned from the RPC node: %v", err), 1)
|
||||
}
|
||||
txHash, err := c.SignAndPushInvocationTx(script, acc, 0, gas, cosigners)
|
||||
txHash, err := c.SignAndPushInvocationTx(script, acc, resp.GasConsumed, gas, cosigners)
|
||||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("failed to push invocation tx: %v", err), 1)
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ ApplicationConfiguration:
|
|||
MinPeers: 5
|
||||
RPC:
|
||||
Enabled: true
|
||||
MaxGasInvoke: 10
|
||||
EnableCORSWorkaround: false
|
||||
Port: 10332
|
||||
TLSConfig:
|
||||
|
|
|
@ -44,6 +44,7 @@ ApplicationConfiguration:
|
|||
MinPeers: 3
|
||||
RPC:
|
||||
Enabled: true
|
||||
MaxGasInvoke: 10
|
||||
EnableCORSWorkaround: false
|
||||
Port: 30336
|
||||
Prometheus:
|
||||
|
|
|
@ -44,6 +44,7 @@ ApplicationConfiguration:
|
|||
MinPeers: 3
|
||||
RPC:
|
||||
Enabled: true
|
||||
MaxGasInvoke: 10
|
||||
EnableCORSWorkaround: false
|
||||
Port: 30333
|
||||
Prometheus:
|
||||
|
|
|
@ -44,6 +44,7 @@ ApplicationConfiguration:
|
|||
MinPeers: 3
|
||||
RPC:
|
||||
Enabled: true
|
||||
MaxGasInvoke: 10
|
||||
EnableCORSWorkaround: false
|
||||
Port: 30335
|
||||
Prometheus:
|
||||
|
|
|
@ -44,6 +44,7 @@ ApplicationConfiguration:
|
|||
MinPeers: 3
|
||||
RPC:
|
||||
Enabled: true
|
||||
MaxGasInvoke: 10
|
||||
EnableCORSWorkaround: false
|
||||
Port: 30334
|
||||
Prometheus:
|
||||
|
|
|
@ -44,6 +44,7 @@ ApplicationConfiguration:
|
|||
MinPeers: 3
|
||||
RPC:
|
||||
Enabled: true
|
||||
MaxGasInvoke: 10
|
||||
EnableCORSWorkaround: false
|
||||
Port: 20331
|
||||
TLSConfig:
|
||||
|
|
|
@ -48,6 +48,7 @@ ApplicationConfiguration:
|
|||
MinPeers: 5
|
||||
RPC:
|
||||
Enabled: true
|
||||
MaxGasInvoke: 10
|
||||
EnableCORSWorkaround: false
|
||||
Port: 20332
|
||||
TLSConfig:
|
||||
|
|
|
@ -43,6 +43,7 @@ ApplicationConfiguration:
|
|||
MinPeers: 1
|
||||
RPC:
|
||||
Address: 127.0.0.1
|
||||
MaxGasInvoke: 10
|
||||
Enabled: true
|
||||
EnableCORSWorkaround: false
|
||||
Port: 0 # let the system choose port dynamically
|
||||
|
|
|
@ -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)
|
||||
|
@ -257,6 +257,7 @@ func signTx(t *testing.T, feePerByte int64, txs ...*transaction.Transaction) {
|
|||
privNetKeys[i] = testchain.PrivateKey(i)
|
||||
validators[i] = privNetKeys[i].PublicKey()
|
||||
}
|
||||
privNetKeys = privNetKeys[:3]
|
||||
rawScript, err := smartcontract.CreateMultiSigRedeemScript(3, validators)
|
||||
require.NoError(t, err)
|
||||
for _, tx := range txs {
|
||||
|
|
|
@ -49,6 +49,8 @@ const (
|
|||
commitType messageType = 0x30
|
||||
recoveryRequestType messageType = 0x40
|
||||
recoveryMessageType messageType = 0x41
|
||||
|
||||
payloadGasLimit = 2000000 // 0.02 GAS
|
||||
)
|
||||
|
||||
// ViewNumber implements payload.ConsensusPayload interface.
|
||||
|
@ -221,6 +223,7 @@ func (p *Payload) Verify(scriptHash util.Uint160) bool {
|
|||
}
|
||||
|
||||
v := vm.New()
|
||||
v.GasLimit = payloadGasLimit
|
||||
v.RegisterInteropGetter(crypto.GetInterop(&interop.Context{Container: p}))
|
||||
v.LoadScript(verification)
|
||||
v.LoadScript(p.Witness.InvocationScript)
|
||||
|
|
|
@ -35,7 +35,8 @@ const (
|
|||
headerBatchCount = 2000
|
||||
version = "0.1.0"
|
||||
|
||||
defaultMemPoolSize = 50000
|
||||
defaultMemPoolSize = 50000
|
||||
verificationGasLimit = 100000000 // 1 GAS
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -567,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 {
|
||||
|
@ -1299,13 +1301,15 @@ func ScriptFromWitness(hash util.Uint160, witness *transaction.Witness) ([]byte,
|
|||
}
|
||||
|
||||
// verifyHashAgainstScript verifies given hash against the given witness.
|
||||
func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transaction.Witness, interopCtx *interop.Context, useKeys bool) error {
|
||||
func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transaction.Witness, interopCtx *interop.Context, useKeys bool, gas int64) error {
|
||||
verification, err := ScriptFromWitness(hash, witness)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vm := SpawnVM(interopCtx)
|
||||
vm.SetPriceGetter(getPrice)
|
||||
vm.GasLimit = gas
|
||||
vm.LoadScriptWithFlags(verification, smartcontract.ReadOnly)
|
||||
vm.LoadScript(witness.InvocationScript)
|
||||
if useKeys {
|
||||
|
@ -1360,7 +1364,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)
|
||||
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)
|
||||
|
@ -1380,7 +1384,7 @@ func (bc *Blockchain) verifyHeaderWitnesses(currHeader, prevHeader *block.Header
|
|||
}
|
||||
interopCtx := bc.newInteropContext(trigger.Verification, bc.dao, nil, nil)
|
||||
interopCtx.Container = currHeader
|
||||
return bc.verifyHashAgainstScript(hash, &currHeader.Script, interopCtx, true)
|
||||
return bc.verifyHashAgainstScript(hash, &currHeader.Script, interopCtx, true, verificationGasLimit)
|
||||
}
|
||||
|
||||
// GoverningTokenHash returns the governing token (NEO) native contract hash.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/crypto"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
|
@ -17,10 +18,6 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||
)
|
||||
|
||||
// ecdsaVerifyInteropPrice returns the price of Neo.Crypto.ECDsaVerify
|
||||
// syscall to calculate NetworkFee for transaction
|
||||
const ecdsaVerifyInteropPrice = 100000
|
||||
|
||||
var (
|
||||
// governingTokenTX represents transaction that is used to create
|
||||
// governing (NEO) token. It's a part of the genesis block.
|
||||
|
@ -138,13 +135,13 @@ func CalculateNetworkFee(script []byte) (int64, int) {
|
|||
)
|
||||
if vm.IsSignatureContract(script) {
|
||||
size += 67 + io.GetVarSize(script)
|
||||
netFee += opcodePrice(opcode.PUSHDATA1, opcode.PUSHNULL) + ecdsaVerifyInteropPrice
|
||||
} else if n, pubs, ok := vm.ParseMultiSigContract(script); ok {
|
||||
m := len(pubs)
|
||||
netFee += opcodePrice(opcode.PUSHDATA1, opcode.PUSHNULL) + crypto.ECDSAVerifyPrice
|
||||
} else if m, pubs, ok := vm.ParseMultiSigContract(script); ok {
|
||||
n := len(pubs)
|
||||
sizeInv := 66 * m
|
||||
size += io.GetVarSize(sizeInv) + sizeInv + io.GetVarSize(script)
|
||||
netFee += calculateMultisigFee(m) + calculateMultisigFee(n)
|
||||
netFee += opcodePrice(opcode.PUSHNULL) + ecdsaVerifyInteropPrice*int64(n)
|
||||
netFee += opcodePrice(opcode.PUSHNULL) + crypto.ECDSAVerifyPrice*int64(n)
|
||||
} else {
|
||||
// We can support more contract types in the future.
|
||||
}
|
||||
|
|
|
@ -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