Merge pull request #1362 from nspcc-dev/feature/verification
Allow to use account with contracts on client
This commit is contained in:
commit
9e0c13b69d
9 changed files with 203 additions and 35 deletions
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/cli/options"
|
"github.com/nspcc-dev/neo-go/cli/options"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
|
@ -166,6 +167,20 @@ func NewCommands() []cli.Command {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "import-deployed",
|
||||||
|
Usage: "import deployed contract",
|
||||||
|
UsageText: "import-multisig --wallet <path> --wif <wif> --contract <hash>",
|
||||||
|
Action: importDeployed,
|
||||||
|
Flags: append([]cli.Flag{
|
||||||
|
walletPathFlag,
|
||||||
|
wifFlag,
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "contract, c",
|
||||||
|
Usage: "Contract hash",
|
||||||
|
},
|
||||||
|
}, options.RPC...),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "remove",
|
Name: "remove",
|
||||||
Usage: "remove an account from the wallet",
|
Usage: "remove an account from the wallet",
|
||||||
|
@ -390,7 +405,7 @@ func importMultisig(ctx *cli.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func importWallet(ctx *cli.Context) error {
|
func importDeployed(ctx *cli.Context) error {
|
||||||
wall, err := openWallet(ctx.String("wallet"))
|
wall, err := openWallet(ctx.String("wallet"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cli.NewExitError(err, 1)
|
return cli.NewExitError(err, 1)
|
||||||
|
@ -398,6 +413,56 @@ func importWallet(ctx *cli.Context) error {
|
||||||
|
|
||||||
defer wall.Close()
|
defer wall.Close()
|
||||||
|
|
||||||
|
rawHash := strings.TrimPrefix("0x", ctx.String("contract"))
|
||||||
|
h, err := util.Uint160DecodeStringLE(rawHash)
|
||||||
|
if err != nil {
|
||||||
|
return cli.NewExitError(fmt.Errorf("invalid contract hash: %w", err), 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
acc, err := newAccountFromWIF(ctx.String("wif"))
|
||||||
|
if err != nil {
|
||||||
|
return cli.NewExitError(err, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
gctx, cancel := options.GetTimeoutContext(ctx)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
c, err := options.GetRPCClient(gctx, ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cs, err := c.GetContractState(h)
|
||||||
|
if err != nil {
|
||||||
|
return cli.NewExitError(fmt.Errorf("can't fetch contract info: %w", err), 1)
|
||||||
|
}
|
||||||
|
md := cs.Manifest.ABI.GetMethod(manifest.MethodVerify)
|
||||||
|
if md == nil {
|
||||||
|
return cli.NewExitError("contract has no `verify` method", 1)
|
||||||
|
}
|
||||||
|
acc.Contract.Script = cs.Script
|
||||||
|
for _, p := range md.Parameters {
|
||||||
|
acc.Contract.Parameters = append(acc.Contract.Parameters, wallet.ContractParam{
|
||||||
|
Name: p.Name,
|
||||||
|
Type: p.Type,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
acc.Contract.Deployed = true
|
||||||
|
|
||||||
|
if err := addAccountAndSave(wall, acc); err != nil {
|
||||||
|
return cli.NewExitError(err, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func importWallet(ctx *cli.Context) error {
|
||||||
|
wall, err := openWallet(ctx.String("wallet"))
|
||||||
|
if err != nil {
|
||||||
|
return cli.NewExitError(err, 1)
|
||||||
|
}
|
||||||
|
defer wall.Close()
|
||||||
|
|
||||||
acc, err := newAccountFromWIF(ctx.String("wif"))
|
acc, err := newAccountFromWIF(ctx.String("wif"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cli.NewExitError(err, 1)
|
return cli.NewExitError(err, 1)
|
||||||
|
|
|
@ -226,24 +226,7 @@ func TestCreateBasicChain(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Push some contract into the chain.
|
// Push some contract into the chain.
|
||||||
name := prefix + "test_contract.go"
|
txDeploy, avm := newDeployTx(t, 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.Nonce = getNextNonce()
|
txDeploy.Nonce = getNextNonce()
|
||||||
txDeploy.ValidUntilBlock = validUntilBlock
|
txDeploy.ValidUntilBlock = validUntilBlock
|
||||||
txDeploy.Signers = []transaction.Signer{{Account: priv0ScriptHash}}
|
txDeploy.Signers = []transaction.Signer{{Account: priv0ScriptHash}}
|
||||||
|
@ -255,7 +238,7 @@ func TestCreateBasicChain(t *testing.T) {
|
||||||
t.Logf("Block2 hash: %s", b.Hash().StringLE())
|
t.Logf("Block2 hash: %s", b.Hash().StringLE())
|
||||||
|
|
||||||
// Now invoke this contract.
|
// Now invoke this contract.
|
||||||
script = io.NewBufBinWriter()
|
script := io.NewBufBinWriter()
|
||||||
emit.AppCallWithOperationAndArgs(script.BinWriter, hash.Hash160(avm), "putValue", "testkey", "testvalue")
|
emit.AppCallWithOperationAndArgs(script.BinWriter, hash.Hash160(avm), "putValue", "testkey", "testvalue")
|
||||||
|
|
||||||
txInv := transaction.New(testchain.Network(), script.Bytes(), 1*native.GASFactor)
|
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))
|
require.NoError(t, bc.AddBlock(b))
|
||||||
t.Logf("sendRublesTx: %v", transferTx.Hash().StringLE())
|
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 {
|
if saveChain {
|
||||||
outStream, err := os.Create(prefix + "testblocks.acc")
|
outStream, err := os.Create(prefix + "testblocks.acc")
|
||||||
require.NoError(t, err)
|
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)
|
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) {
|
func addSigners(txs ...*transaction.Transaction) {
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
tx.Signers = []transaction.Signer{{
|
tx.Signers = []transaction.Signer{{
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||||
)
|
)
|
||||||
|
@ -20,6 +21,9 @@ func CheckHashedWitness(ic *interop.Context, hash util.Uint160) (bool, error) {
|
||||||
return checkScope(ic.DAO, tx, ic.VM, hash)
|
return checkScope(ic.DAO, tx, ic.VM, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !ic.VM.Context().GetCallFlags().Has(smartcontract.AllowStates) {
|
||||||
|
return false, errors.New("missing AllowStates call flag")
|
||||||
|
}
|
||||||
return false, errors.New("script container is not a transaction")
|
return false, errors.New("script container is not a transaction")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +53,9 @@ func checkScope(d dao.DAO, tx *transaction.Transaction, v *vm.VM, hash util.Uint
|
||||||
if callingScriptHash.Equals(util.Uint160{}) {
|
if callingScriptHash.Equals(util.Uint160{}) {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
if !v.Context().GetCallFlags().Has(smartcontract.AllowStates) {
|
||||||
|
return false, errors.New("missing AllowStates call flag")
|
||||||
|
}
|
||||||
cs, err := d.GetContractState(callingScriptHash)
|
cs, err := d.GetContractState(callingScriptHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
|
|
@ -77,7 +77,7 @@ var systemInterops = []interop.Function{
|
||||||
{Name: interopnames.SystemJSONDeserialize, Func: json.Deserialize, Price: 500000, ParamCount: 1},
|
{Name: interopnames.SystemJSONDeserialize, Func: json.Deserialize, Price: 500000, ParamCount: 1},
|
||||||
{Name: interopnames.SystemJSONSerialize, Func: json.Serialize, Price: 100000, ParamCount: 1},
|
{Name: interopnames.SystemJSONSerialize, Func: json.Serialize, Price: 100000, ParamCount: 1},
|
||||||
{Name: interopnames.SystemRuntimeCheckWitness, Func: runtime.CheckWitness, Price: 30000,
|
{Name: interopnames.SystemRuntimeCheckWitness, Func: runtime.CheckWitness, Price: 30000,
|
||||||
RequiredFlags: smartcontract.AllowStates, ParamCount: 1},
|
RequiredFlags: smartcontract.NoneFlag, ParamCount: 1},
|
||||||
{Name: interopnames.SystemRuntimeGasLeft, Func: runtime.GasLeft, Price: 400},
|
{Name: interopnames.SystemRuntimeGasLeft, Func: runtime.GasLeft, Price: 400},
|
||||||
{Name: interopnames.SystemRuntimeGetCallingScriptHash, Func: engineGetCallingScriptHash, Price: 400},
|
{Name: interopnames.SystemRuntimeGetCallingScriptHash, Func: engineGetCallingScriptHash, Price: 400},
|
||||||
{Name: interopnames.SystemRuntimeGetEntryScriptHash, Func: engineGetEntryScriptHash, Price: 400},
|
{Name: interopnames.SystemRuntimeGetEntryScriptHash, Func: engineGetEntryScriptHash, Price: 400},
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
|
"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/rpc/response/result"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
"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/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
"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)
|
size := io.GetVarSize(tx)
|
||||||
for i, cosigner := range tx.Signers {
|
for i, cosigner := range tx.Signers {
|
||||||
if accs[i].Contract.Script == nil {
|
if accs[i].Contract.Deployed {
|
||||||
contract, err := c.GetContractState(cosigner.Account)
|
res, err := c.InvokeFunction(cosigner.Account, manifest.MethodVerify, []smartcontract.Parameter{}, tx.Signers)
|
||||||
if err == nil {
|
if err == nil && res.State == "HALT" && len(res.Stack) == 1 {
|
||||||
if contract == nil {
|
r, err := topIntFromStack(res.Stack)
|
||||||
continue
|
if err != nil || r == 0 {
|
||||||
|
return core.ErrVerificationFailed
|
||||||
}
|
}
|
||||||
netFee, sizeDelta := core.CalculateNetworkFee(contract.Script)
|
} else {
|
||||||
tx.NetworkFee += netFee
|
return core.ErrVerificationFailed
|
||||||
size += sizeDelta
|
|
||||||
}
|
}
|
||||||
|
tx.NetworkFee += res.GasConsumed
|
||||||
|
size += io.GetVarSize([]byte{}) * 2 // both scripts are empty
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
netFee, sizeDelta := core.CalculateNetworkFee(accs[i].Contract.Script)
|
netFee, sizeDelta := core.CalculateNetworkFee(accs[i].Contract.Script)
|
||||||
tx.NetworkFee += netFee
|
tx.NetworkFee += netFee
|
||||||
|
|
|
@ -2,6 +2,7 @@ package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
"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)
|
cFeeM, _ := core.CalculateNetworkFee(accs[1].Contract.Script)
|
||||||
require.Equal(t, int64(io.GetVarSize(tx))*feePerByte+cFee+cFeeM+10, tx.NetworkFee)
|
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) {
|
func TestSignAndPushInvocationTx(t *testing.T) {
|
||||||
|
|
|
@ -51,8 +51,11 @@ type rpcTestCase struct {
|
||||||
check func(t *testing.T, e *executor, result interface{})
|
check func(t *testing.T, e *executor, result interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
const testContractHash = "93c4983afe01a75f74c1e56011bd630e9d8cc755"
|
const testContractHash = "4546ec6fcdaa1c3ccdb048526b78624b457b60a4"
|
||||||
const deploymentTxHash = "583cf0e49d69d8854869efc3e97ad741061da478292a7280580789351a39a1ac"
|
const deploymentTxHash = "17be1bbb0fdecae18cd4c6a2db19311f47bd540371e2ea479a46b349a66aa0b3"
|
||||||
|
|
||||||
|
const verifyContractHash = "47ef649f9a77cad161ddaa28b39c7e450e5429e7"
|
||||||
|
const verifyContractAVM = "560340570300412d510830db4121700c14aa8acf859d4fe402b34e673f2156821796a488ebdb30716813cedb2869db289740"
|
||||||
|
|
||||||
var rpcTestCases = map[string][]rpcTestCase{
|
var rpcTestCases = map[string][]rpcTestCase{
|
||||||
"getapplicationlog": {
|
"getapplicationlog": {
|
||||||
|
@ -438,7 +441,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
expected := result.UnclaimedGas{
|
expected := result.UnclaimedGas{
|
||||||
Address: testchain.MultisigScriptHash(),
|
Address: testchain.MultisigScriptHash(),
|
||||||
Unclaimed: *big.NewInt(36000),
|
Unclaimed: *big.NewInt(42000),
|
||||||
}
|
}
|
||||||
assert.Equal(t, expected, *actual)
|
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)
|
require.NoErrorf(t, err, "could not parse response: %s", txOut)
|
||||||
|
|
||||||
assert.Equal(t, *block.Transactions[0], actual.Transaction)
|
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())
|
assert.Equal(t, TXHash, actual.Transaction.Hash())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -999,8 +1002,8 @@ func checkNep5Balances(t *testing.T, e *executor, acc interface{}) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Asset: e.chain.UtilityTokenHash(),
|
Asset: e.chain.UtilityTokenHash(),
|
||||||
Amount: "915.61059740",
|
Amount: "815.59478530",
|
||||||
LastUpdated: 6,
|
LastUpdated: 7,
|
||||||
}},
|
}},
|
||||||
Address: testchain.PrivateKeyByID(0).GetScriptHash().StringLE(),
|
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