Merge pull request #903 from nspcc-dev/fix/tests

rpc: simplify RPC tests
This commit is contained in:
Roman Khimov 2020-04-24 09:41:34 +03:00 committed by GitHub
commit ab9d334182
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 149 additions and 102 deletions

View file

@ -71,17 +71,7 @@ func newBlock(cfg config.ProtocolConfiguration, index uint32, prev util.Uint256,
}
_ = b.RebuildMerkleRoot()
buf := io.NewBufBinWriter()
for i := 0; i < testchain.Size(); i++ {
pKey := testchain.PrivateKey(i)
b := b.GetSignedPart()
sig := pKey.Sign(b)
if len(sig) != 64 {
panic("wrong signature length")
}
emit.Bytes(buf.BinWriter, sig)
}
b.Script.InvocationScript = buf.Bytes()
b.Script.InvocationScript = testchain.Sign(b.GetSignedPart())
return b
}
@ -466,19 +456,6 @@ func TestCreateBasicChain(t *testing.T) {
bw := io.NewBufBinWriter()
txNeoRound.EncodeBinary(bw.BinWriter)
t.Logf("sendrawtransaction: %s", hex.EncodeToString(bw.Bytes()))
// Blocks for `submitblock` test. If you are planning to modify test chain from `testblocks.acc`,
// please, update params value of `empty block` and `positive` tests.
var blocks []*block.Block
minerTx = nextMinerTx(validUntilBlock)
minerTx.Sender = priv0ScriptHash
require.NoError(t, acc0.SignTx(minerTx))
blocks = append(blocks, bc.newBlock(), bc.newBlock(minerTx))
for i, b := range blocks {
data, err := testserdes.EncodeBinary(b)
require.NoError(t, err)
t.Logf("\nblock %v for submitblock test:\n%s", i, hex.EncodeToString(data))
}
}
func newNEP5Transfer(sc, from, to util.Uint160, amount int64) *transaction.Transaction {
@ -508,15 +485,8 @@ func signTx(bc *Blockchain, txs ...*transaction.Transaction) error {
}
for _, tx := range txs {
data := tx.GetSignedPart()
var invoc []byte
for i := 0; i < testchain.Size(); i++ {
priv := testchain.PrivateKey(i)
invoc = append(invoc, getInvocationScript(data, priv)...)
}
tx.Scripts = []transaction.Witness{{
InvocationScript: invoc,
InvocationScript: testchain.Sign(data),
VerificationScript: rawScript,
}}
}

View file

@ -4,8 +4,10 @@ import (
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"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/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
)
// privNetKeys is a list of unencrypted WIFs sorted by public key.
@ -78,3 +80,17 @@ func MultisigScriptHash() util.Uint160 {
func MultisigAddress() string {
return address.Uint160ToString(MultisigScriptHash())
}
// Sign signs data by all consensus nodes and returns invocation script.
func Sign(data []byte) []byte {
buf := io.NewBufBinWriter()
for i := 0; i < Size(); i++ {
pKey := PrivateKey(i)
sig := pKey.Sign(data)
if len(sig) != 64 {
panic("wrong signature length")
}
emit.Bytes(buf.BinWriter, sig)
}
return buf.Bytes()
}

View file

@ -12,8 +12,11 @@ import (
"strconv"
"strings"
"testing"
"time"
"github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/blockchainer"
"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/encoding/address"
@ -22,6 +25,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/rpc/response"
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -402,56 +406,6 @@ var rpcTestCases = map[string][]rpcTestCase{
},
},
"getblockheader": {
{
name: "positive, no verbose",
params: `["8c702625ab05236fda5763bbe168359b7747508e1387e4404217e0418846c94e"]`,
result: func(e *executor) interface{} {
expected := "000000007654fa898eba5ced6ab7a44fe1187e48b80ddd5340499fb2d312cc2fe4a6df1bb31cada0cb85914ee5bd6d11d25289a59203bf65f40232de8ffaa2bb7517f3b50a0ca05e010000005704000000000000e903736ceceeceae1806eee0e3ec61e7cce476ce01fd08010c404def65e6b379e441fe1507d6d031c874e686b854b2afe9843fda5087f76e261e282b4db232079485dcf449678e2358a3d148835b85affba4ecd08a2bf1b556fe0c406b6218df12f8a7060379daf4eed312a85be51ea2fabee826a745547141694a3f49f8a61ac63db7ece1de7fbb54ecb9c5ac244a7fcdd794c9767b4cb2637a9c840c40ebaf64e3b76299d3ccc7e48e197a09af11cc0a80bd636cdef80312c61e24eebaace44cda90d17eb3ba85cfc08079676626966c75a48631b508c39375a8181ec40c402a77786cdaa5e93f0952c834cebdab25475beee0b60fce4263d85b7395bcde993ebee884667def21b7de494097f30c14c626357683680bdbace9667cc03b0da894130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb00"
return &expected
},
},
{
name: "positive, verbose 0",
params: `["8c702625ab05236fda5763bbe168359b7747508e1387e4404217e0418846c94e", 0]`,
result: func(e *executor) interface{} {
expected := "000000007654fa898eba5ced6ab7a44fe1187e48b80ddd5340499fb2d312cc2fe4a6df1bb31cada0cb85914ee5bd6d11d25289a59203bf65f40232de8ffaa2bb7517f3b50a0ca05e010000005704000000000000e903736ceceeceae1806eee0e3ec61e7cce476ce01fd08010c404def65e6b379e441fe1507d6d031c874e686b854b2afe9843fda5087f76e261e282b4db232079485dcf449678e2358a3d148835b85affba4ecd08a2bf1b556fe0c406b6218df12f8a7060379daf4eed312a85be51ea2fabee826a745547141694a3f49f8a61ac63db7ece1de7fbb54ecb9c5ac244a7fcdd794c9767b4cb2637a9c840c40ebaf64e3b76299d3ccc7e48e197a09af11cc0a80bd636cdef80312c61e24eebaace44cda90d17eb3ba85cfc08079676626966c75a48631b508c39375a8181ec40c402a77786cdaa5e93f0952c834cebdab25475beee0b60fce4263d85b7395bcde993ebee884667def21b7de494097f30c14c626357683680bdbace9667cc03b0da894130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb00"
return &expected
},
},
{
name: "positive, verbose !=0",
params: `["8c702625ab05236fda5763bbe168359b7747508e1387e4404217e0418846c94e", 2]`,
result: func(e *executor) interface{} {
hash, err := util.Uint256DecodeStringLE("8c702625ab05236fda5763bbe168359b7747508e1387e4404217e0418846c94e")
if err != nil {
panic("can not decode hash parameter")
}
block, err := e.chain.GetBlock(hash)
if err != nil {
panic("unknown block (update block hash)")
}
header := block.Header()
expected := result.Header{
Hash: header.Hash(),
Size: io.GetVarSize(header),
Version: header.Version,
PrevBlockHash: header.PrevHash,
MerkleRoot: header.MerkleRoot,
Timestamp: header.Timestamp,
Index: header.Index,
Nonce: strconv.FormatUint(header.ConsensusData, 16),
NextConsensus: address.Uint160ToString(header.NextConsensus),
Script: header.Script,
Confirmations: e.chain.BlockHeight() - header.Index + 1,
}
nextHash := e.chain.GetHeaderHash(int(header.Index) + 1)
if !hash.Equals(util.Uint256{}) {
expected.NextBlockHash = &nextHash
}
return &expected
},
},
{
name: "invalid verbose type",
params: `["614a9085dc55fd0539ad3a9d68d8b8e7c52328da905c87bfe8cfca57a5c3c02f", true]`,
@ -818,17 +772,6 @@ var rpcTestCases = map[string][]rpcTestCase{
},
},
"submitblock": {
{
// If you are planning to modify test chain from `testblocks.acc`, please, update param value (first block)
name: "empty block",
params: `["0000000007b57cc5c1902010f968adc0cb96c87e1a97005ee1ddc8510cf6272e812221820000000000000000000000000000000000000000000000000000000000000000db0ca05ed10000005704000000000000e903736ceceeceae1806eee0e3ec61e7cce476ce01fd08010c4050da0a5d3672a56ad442a1e58129e8df0ca4c3235e33e86b8332144a253c559a35742206f87866cfdb8f809cac8b4cc9bc901372161a7a577ed6490158c492a60c4007bb4e7776a3102c183ba8e5aec77b9a436e6629f67150a77689e25c32df427b5a4c77f2198f0554fbc1ef2f2e2605f3a84d5789a48e90883203d491172c3f0d0c4049b0a16bb1decc7673d9bdca2e3a613b1102a7774e405d3d1ce1fff276acb8d6d0eff980554792d21603b9d9b6dd50941ea3eda4efad4922b063571ea49108df0c401bb53c5d0fcf94beeb7c1f0d9d9998b7af5f29c906492d49f4650de250826926cfc2c7bdb6369139563a0ed74039c4fb69c0e63ced82fc2a2b74778c7287ca5694130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb00"]`,
fail: true,
},
{
name: "invalid block height",
params: `["000000005fb86f62eafe8e9246bc0d1648e4e5c8389dee9fb7fe03fcc6772ec8c5e4ec2aedb908054ac1409be5f77d5369c6e03490b2f6676d68d0b3370f8159e0fdadf99bc05f5e030000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd0401406f299c82b513f59f5bd120317974852c9694c6e10db1ef2f1bb848b1a33e47a08f8dc03ee784166b2060a94cd4e7af88899b39787938f7f2763ea4d2182776ed40f3bafd85214fef38a4836ca97793001ea411f553c51e88781f7b916c59c145bff28314b6e7ea246789422a996fc4937e290a1b40f6b97c5222540f65b0d47aca40d2b3d19203d456428bfdb529e846285052105957385b65388b9a617f6e2d56a64ec41aa73439eafccb52987bb1975c9b67518b053d9e61b445e4a3377dbc206640bd688489bd62adf6bed9d61a73905b9591eb87053c6f0f4dd70f3bee7295541b490caef044b55b6f9f01dc4a05a756a3f2edd06f5adcbe4e984c1e552f9023f08b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae0100000000000000000000"]`,
fail: true,
},
{
name: "invalid hex",
params: `["000000005gb86f62eafe8e9246bc0d1648e4e5c8389dee9fb7fe03fcc6772ec8c5e4ec2aedb908054ac1409be5f77d5369c6e03490b2f6676d68d0b3370f8159e0fdadf99bc05f5e030000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd0401406f299c82b513f59f5bd120317974852c9694c6e10db1ef2f1bb848b1a33e47a08f8dc03ee784166b2060a94cd4e7af88899b39787938f7f2763ea4d2182776ed40f3bafd85214fef38a4836ca97793001ea411f553c51e88781f7b916c59c145bff28314b6e7ea246789422a996fc4937e290a1b40f6b97c5222540f65b0d47aca40d2b3d19203d456428bfdb529e846285052105957385b65388b9a617f6e2d56a64ec41aa73439eafccb52987bb1975c9b67518b053d9e61b445e4a3377dbc206640bd688489bd62adf6bed9d61a73905b9591eb87053c6f0f4dd70f3bee7295541b490caef044b55b6f9f01dc4a05a756a3f2edd06f5adcbe4e984c1e552f9023f08b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae0100000000000000000000"]`,
@ -844,15 +787,6 @@ var rpcTestCases = map[string][]rpcTestCase{
params: `[]`,
fail: true,
},
{
name: "positive",
// If you are planning to modify test chain from `testblocks.acc`, please, update param value (second block)
params: `["0000000007b57cc5c1902010f968adc0cb96c87e1a97005ee1ddc8510cf6272e81222182d13aba8fa5e27a16382d64ce3751b9ffaa3f81f634fbd4399bf048d58e7c5c7adb0ca05ed10000005704000000000000e903736ceceeceae1806eee0e3ec61e7cce476ce01fd08010c405545b3ad5912f043ed975176ba1f02f64119f10d63385a472ecaef6aa4a2b04237946e66e74e53435a19abd59fb14dfa7d64d29a39b8655c23ed87c74d2674d70c40e6880ad9677b3b28f6c0a3c9172f8ff98dcc5ad7c78768e34481799edebcf5bbcafa583740808bf0668bdd07288b004b11f52db517ef68482e8cf1f5774ef6ba0c406ea533f7f49310e9156d7c6032fbc8a63d20777e9e850fdc0a0d3e3d9c5b9340e4d22eba14a8a1446b886a34dee437e6cfd4f2b6eed9048291610330968c225a0c401a7c49e25676aabd511bcf556970c28e530df561f89dd7d12285e848ef234273eca90a9344420ace9c84df798925d4c547ea120183ae5562b6507f55acb52c7e94130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb0100001400000075a94799633ed955dd85a8af314a5b435ab51903b004000000000001420c40b2eb026301528ce76f07caa304f26e3aaa08997e82f12a94350ec1354683d165f4a02c87f2250dae39abbf55dd9a0bd642ecbbbb17136ca2c202bc5757c1495c290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4"]`,
result: func(e *executor) interface{} {
v := true
return &v
},
},
},
"validateaddress": {
{
@ -911,6 +845,42 @@ func TestRPC(t *testing.T) {
})
}
t.Run("submit", func(t *testing.T) {
rpc := `{"jsonrpc": "2.0", "id": 1, "method": "submitblock", "params": ["%s"]}`
t.Run("empty", func(t *testing.T) {
s := newBlock(t, chain, 1)
body := doRPCCall(fmt.Sprintf(rpc, s), handler, t)
checkErrGetResult(t, body, true)
})
wif := testchain.WIF(0)
acc, err := wallet.NewAccountFromWIF(wif)
require.NoError(t, err)
newTx := func() *transaction.Transaction {
height := chain.BlockHeight()
tx := transaction.NewMinerTXWithNonce(height + 1)
tx.ValidUntilBlock = height + 10
tx.Sender = acc.PrivateKey().GetScriptHash()
require.NoError(t, acc.SignTx(tx))
return tx
}
t.Run("invalid height", func(t *testing.T) {
b := newBlock(t, chain, 2, newTx())
body := doRPCCall(fmt.Sprintf(rpc, encodeBlock(t, b)), handler, t)
checkErrGetResult(t, body, true)
})
t.Run("positive", func(t *testing.T) {
b := newBlock(t, chain, 1, newTx())
body := doRPCCall(fmt.Sprintf(rpc, encodeBlock(t, b)), handler, t)
data := checkErrGetResult(t, body, false)
var res bool
require.NoError(t, json.Unmarshal(data, &res))
require.True(t, res)
})
})
t.Run("getrawtransaction", func(t *testing.T) {
block, _ := chain.GetBlock(chain.GetHeaderHash(0))
TXHash := block.Transactions[1].Hash()
@ -960,6 +930,55 @@ func TestRPC(t *testing.T) {
assert.Equal(t, TXHash, actual.Transaction.Hash())
})
t.Run("getblockheader_positive", func(t *testing.T) {
rpc := `{"jsonrpc": "2.0", "id": 1, "method": "getblockheader", "params": %s}`
testHeaderHash := chain.GetHeaderHash(1).StringLE()
hdr := e.getHeader(testHeaderHash)
runCase := func(t *testing.T, rpc string, expected, actual interface{}) {
body := doRPCCall(rpc, handler, t)
data := checkErrGetResult(t, body, false)
require.NoError(t, json.Unmarshal(data, actual))
require.Equal(t, expected, actual)
}
t.Run("no verbose", func(t *testing.T) {
w := io.NewBufBinWriter()
hdr.EncodeBinary(w.BinWriter)
require.NoError(t, w.Err)
encoded := hex.EncodeToString(w.Bytes())
t.Run("missing", func(t *testing.T) {
runCase(t, fmt.Sprintf(rpc, `["`+testHeaderHash+`"]`), &encoded, new(string))
})
t.Run("verbose=0", func(t *testing.T) {
runCase(t, fmt.Sprintf(rpc, `["`+testHeaderHash+`", 0]`), &encoded, new(string))
})
})
t.Run("verbose != 0", func(t *testing.T) {
nextHash := chain.GetHeaderHash(int(hdr.Index) + 1)
expected := &result.Header{
Hash: hdr.Hash(),
Size: io.GetVarSize(hdr),
Version: hdr.Version,
PrevBlockHash: hdr.PrevHash,
MerkleRoot: hdr.MerkleRoot,
Timestamp: hdr.Timestamp,
Index: hdr.Index,
Nonce: strconv.FormatUint(hdr.ConsensusData, 16),
NextConsensus: address.Uint160ToString(hdr.NextConsensus),
Script: hdr.Script,
Confirmations: e.chain.BlockHeight() - hdr.Index + 1,
NextBlockHash: &nextHash,
}
rpc := fmt.Sprintf(rpc, `["`+testHeaderHash+`", 2]`)
runCase(t, rpc, expected, new(result.Header))
})
})
t.Run("gettxout", func(t *testing.T) {
block, _ := chain.GetBlock(chain.GetHeaderHash(0))
tx := block.Transactions[3]
@ -1002,6 +1021,48 @@ func TestRPC(t *testing.T) {
})
}
func (e *executor) getHeader(s string) *block.Header {
hash, err := util.Uint256DecodeStringLE(s)
if err != nil {
panic("can not decode hash parameter")
}
block, err := e.chain.GetBlock(hash)
if err != nil {
panic("unknown block (update block hash)")
}
return block.Header()
}
func encodeBlock(t *testing.T, b *block.Block) string {
w := io.NewBufBinWriter()
b.EncodeBinary(w.BinWriter)
require.NoError(t, w.Err)
return hex.EncodeToString(w.Bytes())
}
func newBlock(t *testing.T, bc blockchainer.Blockchainer, index uint32, txs ...*transaction.Transaction) *block.Block {
witness := transaction.Witness{VerificationScript: testchain.MultisigVerificationScript()}
height := bc.BlockHeight()
h := bc.GetHeaderHash(int(height))
hdr, err := bc.GetHeader(h)
require.NoError(t, err)
b := &block.Block{
Base: block.Base{
PrevHash: hdr.Hash(),
Timestamp: uint32(time.Now().UTC().Unix()) + hdr.Index,
Index: hdr.Index + index,
ConsensusData: 1111,
NextConsensus: witness.ScriptHash(),
Script: witness,
},
Transactions: txs,
}
_ = b.RebuildMerkleRoot()
b.Script.InvocationScript = testchain.Sign(b.GetSignedPart())
return b
}
func (tc rpcTestCase) getResultPair(e *executor) (expected interface{}, res interface{}) {
expected = tc.result(e)
resVal := reflect.New(reflect.TypeOf(expected).Elem())