rpc/client: allow to use contract accounts in AddNetworkFee
This commit is contained in:
parent
f6319f80e8
commit
9c7168e4e8
6 changed files with 129 additions and 33 deletions
|
@ -226,24 +226,7 @@ func TestCreateBasicChain(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
// Push some contract into the chain.
|
||||
name := prefix + "test_contract.go"
|
||||
c, err := ioutil.ReadFile(name)
|
||||
require.NoError(t, err)
|
||||
avm, di, err := compiler.CompileWithDebugInfo(name, bytes.NewReader(c))
|
||||
require.NoError(t, err)
|
||||
t.Logf("contractHash: %s", hash.Hash160(avm).StringLE())
|
||||
|
||||
script := io.NewBufBinWriter()
|
||||
m, err := di.ConvertToManifest(smartcontract.HasStorage, nil)
|
||||
require.NoError(t, err)
|
||||
bs, err := m.MarshalJSON()
|
||||
require.NoError(t, err)
|
||||
emit.Bytes(script.BinWriter, bs)
|
||||
emit.Bytes(script.BinWriter, avm)
|
||||
emit.Syscall(script.BinWriter, interopnames.SystemContractCreate)
|
||||
txScript := script.Bytes()
|
||||
|
||||
txDeploy := transaction.New(testchain.Network(), txScript, 100*native.GASFactor)
|
||||
txDeploy, avm := newDeployTx(t, prefix+"test_contract.go")
|
||||
txDeploy.Nonce = getNextNonce()
|
||||
txDeploy.ValidUntilBlock = validUntilBlock
|
||||
txDeploy.Signers = []transaction.Signer{{Account: priv0ScriptHash}}
|
||||
|
@ -255,7 +238,7 @@ func TestCreateBasicChain(t *testing.T) {
|
|||
t.Logf("Block2 hash: %s", b.Hash().StringLE())
|
||||
|
||||
// Now invoke this contract.
|
||||
script = io.NewBufBinWriter()
|
||||
script := io.NewBufBinWriter()
|
||||
emit.AppCallWithOperationAndArgs(script.BinWriter, hash.Hash160(avm), "putValue", "testkey", "testvalue")
|
||||
|
||||
txInv := transaction.New(testchain.Network(), script.Bytes(), 1*native.GASFactor)
|
||||
|
@ -330,6 +313,16 @@ func TestCreateBasicChain(t *testing.T) {
|
|||
require.NoError(t, bc.AddBlock(b))
|
||||
t.Logf("sendRublesTx: %v", transferTx.Hash().StringLE())
|
||||
|
||||
// Push verification contract into the chain.
|
||||
txDeploy2, _ := newDeployTx(t, prefix+"verification_contract.go")
|
||||
txDeploy2.Nonce = getNextNonce()
|
||||
txDeploy2.ValidUntilBlock = validUntilBlock
|
||||
txDeploy2.Signers = []transaction.Signer{{Account: priv0ScriptHash}}
|
||||
require.NoError(t, addNetworkFee(bc, txDeploy2, acc0))
|
||||
require.NoError(t, acc0.SignTx(txDeploy2))
|
||||
b = bc.newBlock(txDeploy2)
|
||||
require.NoError(t, bc.AddBlock(b))
|
||||
|
||||
if saveChain {
|
||||
outStream, err := os.Create(prefix + "testblocks.acc")
|
||||
require.NoError(t, err)
|
||||
|
@ -378,6 +371,27 @@ func newNEP5Transfer(sc, from, to util.Uint160, amount int64) *transaction.Trans
|
|||
return transaction.New(testchain.Network(), script, 10000000)
|
||||
}
|
||||
|
||||
func newDeployTx(t *testing.T, name string) (*transaction.Transaction, []byte) {
|
||||
c, err := ioutil.ReadFile(name)
|
||||
require.NoError(t, err)
|
||||
avm, di, err := compiler.CompileWithDebugInfo(name, bytes.NewReader(c))
|
||||
require.NoError(t, err)
|
||||
t.Logf("contractHash (%s): %s", name, hash.Hash160(avm).StringLE())
|
||||
t.Logf("contractScript: %x", avm)
|
||||
|
||||
script := io.NewBufBinWriter()
|
||||
m, err := di.ConvertToManifest(smartcontract.HasStorage, nil)
|
||||
require.NoError(t, err)
|
||||
bs, err := m.MarshalJSON()
|
||||
require.NoError(t, err)
|
||||
emit.Bytes(script.BinWriter, bs)
|
||||
emit.Bytes(script.BinWriter, avm)
|
||||
emit.Syscall(script.BinWriter, interopnames.SystemContractCreate)
|
||||
txScript := script.Bytes()
|
||||
|
||||
return transaction.New(testchain.Network(), txScript, 100*native.GASFactor), avm
|
||||
}
|
||||
|
||||
func addSigners(txs ...*transaction.Transaction) {
|
||||
for _, tx := range txs {
|
||||
tx.Signers = []transaction.Signer{{
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
)
|
||||
|
@ -499,16 +500,19 @@ func (c *Client) AddNetworkFee(tx *transaction.Transaction, extraFee int64, accs
|
|||
}
|
||||
size := io.GetVarSize(tx)
|
||||
for i, cosigner := range tx.Signers {
|
||||
if accs[i].Contract.Script == nil {
|
||||
contract, err := c.GetContractState(cosigner.Account)
|
||||
if err == nil {
|
||||
if contract == nil {
|
||||
continue
|
||||
if accs[i].Contract.Deployed {
|
||||
res, err := c.InvokeFunction(cosigner.Account, manifest.MethodVerify, []smartcontract.Parameter{}, tx.Signers)
|
||||
if err == nil && res.State == "HALT" && len(res.Stack) == 1 {
|
||||
r, err := topIntFromStack(res.Stack)
|
||||
if err != nil || r == 0 {
|
||||
return core.ErrVerificationFailed
|
||||
}
|
||||
netFee, sizeDelta := core.CalculateNetworkFee(contract.Script)
|
||||
tx.NetworkFee += netFee
|
||||
size += sizeDelta
|
||||
} else {
|
||||
return core.ErrVerificationFailed
|
||||
}
|
||||
tx.NetworkFee += res.GasConsumed
|
||||
size += io.GetVarSize([]byte{}) * 2 // both scripts are empty
|
||||
continue
|
||||
}
|
||||
netFee, sizeDelta := core.CalculateNetworkFee(accs[i].Contract.Script)
|
||||
tx.NetworkFee += netFee
|
||||
|
|
|
@ -2,6 +2,7 @@ package server
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||
|
@ -132,6 +133,65 @@ func TestAddNetworkFee(t *testing.T) {
|
|||
cFeeM, _ := core.CalculateNetworkFee(accs[1].Contract.Script)
|
||||
require.Equal(t, int64(io.GetVarSize(tx))*feePerByte+cFee+cFeeM+10, tx.NetworkFee)
|
||||
})
|
||||
t.Run("Contract", func(t *testing.T) {
|
||||
tx := transaction.New(testchain.Network(), []byte{byte(opcode.PUSH1)}, 0)
|
||||
priv := testchain.PrivateKeyByID(0)
|
||||
acc1, err := wallet.NewAccountFromWIF(priv.WIF())
|
||||
require.NoError(t, err)
|
||||
acc1.Contract.Deployed = true
|
||||
acc1.Contract.Script, _ = hex.DecodeString(verifyContractAVM)
|
||||
h, _ := util.Uint160DecodeStringLE(verifyContractHash)
|
||||
tx.ValidUntilBlock = chain.BlockHeight() + 10
|
||||
|
||||
t.Run("Valid", func(t *testing.T) {
|
||||
acc0, err := wallet.NewAccountFromWIF(priv.WIF())
|
||||
require.NoError(t, err)
|
||||
tx.Signers = []transaction.Signer{
|
||||
{
|
||||
Account: acc0.PrivateKey().GetScriptHash(),
|
||||
Scopes: transaction.CalledByEntry,
|
||||
},
|
||||
{
|
||||
Account: h,
|
||||
Scopes: transaction.Global,
|
||||
},
|
||||
}
|
||||
require.NoError(t, c.AddNetworkFee(tx, 10, acc0, acc1))
|
||||
require.NoError(t, acc0.SignTx(tx))
|
||||
tx.Scripts = append(tx.Scripts, transaction.Witness{})
|
||||
require.NoError(t, chain.VerifyTx(tx))
|
||||
})
|
||||
t.Run("Invalid", func(t *testing.T) {
|
||||
acc0, err := wallet.NewAccount()
|
||||
require.NoError(t, err)
|
||||
tx.Signers = []transaction.Signer{
|
||||
{
|
||||
Account: acc0.PrivateKey().GetScriptHash(),
|
||||
Scopes: transaction.CalledByEntry,
|
||||
},
|
||||
{
|
||||
Account: h,
|
||||
Scopes: transaction.Global,
|
||||
},
|
||||
}
|
||||
require.Error(t, c.AddNetworkFee(tx, 10, acc0, acc1))
|
||||
})
|
||||
t.Run("InvalidContract", func(t *testing.T) {
|
||||
acc0, err := wallet.NewAccountFromWIF(priv.WIF())
|
||||
require.NoError(t, err)
|
||||
tx.Signers = []transaction.Signer{
|
||||
{
|
||||
Account: acc0.PrivateKey().GetScriptHash(),
|
||||
Scopes: transaction.CalledByEntry,
|
||||
},
|
||||
{
|
||||
Account: util.Uint160{},
|
||||
Scopes: transaction.Global,
|
||||
},
|
||||
}
|
||||
require.Error(t, c.AddNetworkFee(tx, 10, acc0, acc1))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestSignAndPushInvocationTx(t *testing.T) {
|
||||
|
|
|
@ -51,8 +51,11 @@ type rpcTestCase struct {
|
|||
check func(t *testing.T, e *executor, result interface{})
|
||||
}
|
||||
|
||||
const testContractHash = "93c4983afe01a75f74c1e56011bd630e9d8cc755"
|
||||
const deploymentTxHash = "583cf0e49d69d8854869efc3e97ad741061da478292a7280580789351a39a1ac"
|
||||
const testContractHash = "4546ec6fcdaa1c3ccdb048526b78624b457b60a4"
|
||||
const deploymentTxHash = "17be1bbb0fdecae18cd4c6a2db19311f47bd540371e2ea479a46b349a66aa0b3"
|
||||
|
||||
const verifyContractHash = "47ef649f9a77cad161ddaa28b39c7e450e5429e7"
|
||||
const verifyContractAVM = "560340570300412d510830db4121700c14aa8acf859d4fe402b34e673f2156821796a488ebdb30716813cedb2869db289740"
|
||||
|
||||
var rpcTestCases = map[string][]rpcTestCase{
|
||||
"getapplicationlog": {
|
||||
|
@ -438,7 +441,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
|||
require.True(t, ok)
|
||||
expected := result.UnclaimedGas{
|
||||
Address: testchain.MultisigScriptHash(),
|
||||
Unclaimed: *big.NewInt(36000),
|
||||
Unclaimed: *big.NewInt(42000),
|
||||
}
|
||||
assert.Equal(t, expected, *actual)
|
||||
},
|
||||
|
@ -814,7 +817,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) []
|
|||
require.NoErrorf(t, err, "could not parse response: %s", txOut)
|
||||
|
||||
assert.Equal(t, *block.Transactions[0], actual.Transaction)
|
||||
assert.Equal(t, 8, actual.Confirmations)
|
||||
assert.Equal(t, 9, actual.Confirmations)
|
||||
assert.Equal(t, TXHash, actual.Transaction.Hash())
|
||||
})
|
||||
|
||||
|
@ -999,8 +1002,8 @@ func checkNep5Balances(t *testing.T, e *executor, acc interface{}) {
|
|||
},
|
||||
{
|
||||
Asset: e.chain.UtilityTokenHash(),
|
||||
Amount: "915.61059740",
|
||||
LastUpdated: 6,
|
||||
Amount: "815.59478530",
|
||||
LastUpdated: 7,
|
||||
}},
|
||||
Address: testchain.PrivateKeyByID(0).GetScriptHash().StringLE(),
|
||||
}
|
||||
|
|
BIN
pkg/rpc/server/testdata/testblocks.acc
vendored
BIN
pkg/rpc/server/testdata/testblocks.acc
vendored
Binary file not shown.
15
pkg/rpc/server/testdata/verification_contract.go
vendored
Normal file
15
pkg/rpc/server/testdata/verification_contract.go
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
package testdata
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/convert"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/util"
|
||||
)
|
||||
|
||||
// Verify is a verification contract method.
|
||||
// It returns true iff it is signed by NbTiM6h8r99kpRtb428XcsUk1TzKed2gTc (id-0 private key from testchain).
|
||||
func Verify() bool {
|
||||
tx := runtime.GetScriptContainer()
|
||||
addr := util.FromAddress("NbTiM6h8r99kpRtb428XcsUk1TzKed2gTc")
|
||||
return util.Equals(convert.ToByteArray(tx.Sender), convert.ToByteArray(addr))
|
||||
}
|
Loading…
Reference in a new issue