core: add validUntilBlock field to transaction

1. closes #841

2. Commented out test cases where binary transaction are used.
These test cases marked with `TODO NEO3.0: Update binary` and need to be
updated.

3. Updated other tests.

4. Added cache to calculateValidUntilBlock() RPC-client method.
This commit is contained in:
Anna Shaleva 2020-04-15 09:50:13 +03:00
parent 1e3c36433f
commit 5fa11987d2
16 changed files with 280 additions and 126 deletions

View file

@ -264,6 +264,11 @@ func claimGas(ctx *cli.Context) error {
}
tx := transaction.NewClaimTX(&claim)
validUntilBlock, err := c.CalculateValidUntilBlock()
if err != nil {
return cli.NewExitError(err, 1)
}
tx.ValidUntilBlock = validUntilBlock
tx.AddOutput(&transaction.Output{
AssetID: core.UtilityTokenID(),
@ -510,6 +515,11 @@ func transferAsset(ctx *cli.Context) error {
}
tx := transaction.NewContractTX()
validUntilBlock, err := c.CalculateValidUntilBlock()
if err != nil {
return cli.NewExitError(err, 1)
}
tx.ValidUntilBlock = validUntilBlock
if err := request.AddInputsAndUnspentsToTx(tx, fromFlag.String(), asset, amount, c); err != nil {
return cli.NewExitError(err, 1)
}

View file

@ -19,6 +19,7 @@ import (
func TestNewService(t *testing.T) {
srv := newTestService(t)
tx := transaction.NewMinerTX()
tx.ValidUntilBlock = 1
require.NoError(t, srv.Chain.PoolTx(tx))
var txx []block.Transaction
@ -30,11 +31,11 @@ func TestNewService(t *testing.T) {
func TestService_GetVerified(t *testing.T) {
srv := newTestService(t)
txs := []*transaction.Transaction{
transaction.NewMinerTXWithNonce(123),
transaction.NewMinerTXWithNonce(124),
transaction.NewMinerTXWithNonce(125),
transaction.NewMinerTXWithNonce(126),
var txs []*transaction.Transaction
for i := 0; i < 4; i++ {
tx := transaction.NewMinerTXWithNonce(123 + uint32(i))
tx.ValidUntilBlock = 1
txs = append(txs, tx)
}
require.NoError(t, srv.Chain.PoolTx(txs[3]))
@ -107,6 +108,7 @@ func TestService_getTx(t *testing.T) {
t.Run("transaction in mempool", func(t *testing.T) {
tx := transaction.NewMinerTXWithNonce(1234)
tx.ValidUntilBlock = 1
h := tx.Hash()
require.Equal(t, nil, srv.getTx(h))
@ -120,6 +122,7 @@ func TestService_getTx(t *testing.T) {
t.Run("transaction in local cache", func(t *testing.T) {
tx := transaction.NewMinerTXWithNonce(4321)
tx.ValidUntilBlock = 1
h := tx.Hash()
require.Equal(t, nil, srv.getTx(h))

View file

@ -1,7 +1,6 @@
package consensus
import (
"encoding/hex"
"math/rand"
"testing"
@ -73,6 +72,8 @@ func TestConsensusPayload_Setters(t *testing.T) {
require.Equal(t, pl, p.GetRecoveryMessage())
}
//TODO NEO3.0: Update binary
/*
func TestConsensusPayload_Hash(t *testing.T) {
dataHex := "00000000d8fb8d3b143b5f98468ef701909c976505a110a01e26c5e99be9a90cff979199b6fc33000400000000008d2000184dc95de24018f9ad71f4448a2b438eaca8b4b2ab6b4524b5a69a45d920c35103f3901444320656c390ff39c0062f5e8e138ce446a40c7e4ba1af1f8247ebbdf49295933715d3a67949714ff924f8a28cec5b954c71eca3bfaf0e9d4b1f87b4e21e9ba4ae18f97de71501b5c5d07edc200bd66a46b9b28b1a371f2195c10b0af90000e24018f900000000014140c9faaee59942f58da0e5268bc199632f2a3ad0fcbee68681a4437f140b49512e8d9efc6880eb44d3490782895a5794f35eeccee2923ce0c76fa7a1890f934eac232103c089d7122b840a4935234e82e26ae5efd0c2acb627239dc9f207311337b6f2c1ac"
data, err := hex.DecodeString(dataHex)
@ -82,7 +83,7 @@ func TestConsensusPayload_Hash(t *testing.T) {
require.NoError(t, testserdes.DecodeBinary(data, &p))
require.Equal(t, p.Hash().String(), "45859759c8491597804f1922773947e0d37bf54484af82f80cd642f7b063aa56")
}
*/
func TestConsensusPayload_Serializable(t *testing.T) {
for _, mt := range messageTypes {
p := randomPayload(t, mt)

View file

@ -1,15 +1,12 @@
package consensus
import (
"encoding/hex"
gio "io"
"testing"
"github.com/nspcc-dev/dbft/crypto"
"github.com/nspcc-dev/dbft/payload"
"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/io"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/stretchr/testify/require"
)
@ -114,6 +111,8 @@ func TestRecoveryMessage_Setters(t *testing.T) {
})
}
//TODO NEO3.0: Update binary
/*
func TestRecoveryMessage_DecodeFromTestnet(t *testing.T) {
hexDump := "00000000924b2fa6728782b6afb94873a377c49f31573005e7f2945beb27158ec2e887300d180000010000000000" +
"fd29024100000120003db64b5e8e4ab7138abe65a3be48d3a3f5d10013ab9ffee489706078714f1ea20161e7ba952fdfd5f543891b1fe053af401bc34e9e3f63c90e3c0d6675d156344b00008e4ab71300000000030000414079946c76007e4297b06b074a20dc1d1d6871c74976f244df81bd03f4158a11dd485ed50fc0cc7c6ad352addd8440c5a55d7b7449650bb200e5e58b1fb8a0390c010041403631a490b17ca4fcfe52ed2e7a4ca4c0d3fcca67e73a1ef071f385db1d37cefa7a2de6e56654788647e9142425c29449b0bbfee5c46a96c4bdc79b23c1f862fc02004140147914878c23a9624a62598cebe2c75fdce80c1e19b5c73aa511630f67d4e5a660c63daad7fcfa9bd944f258f51427cb80730b8beb3015a3c2766325bf291a8e02000000989f8fa676ed07885a46ee08af10e1fa1893ef20fbd557dc3c1a9dc498189d5fceff694dcb2085e4969d90c56433b88fd7ba1caef9363829c70419a5314ac36541404f3ee34e11c521f2e31fee439206474d36951443014354ce81b32bd1787e6a92212737f7f72bee59c403ff74292ebf78c4091081174b5921c148cedcbe7bd585000100acfc8399bda6429c64b5c09885a3e4f1a0629f59125df03be956c00f5bb77616c43e43250e96700f80c42ef3e169e9ff9f906518acf0da17c53563ba41d91ebc41409957436afd1736970d4b5e52b8d845663d6b0335a34cf78ece733c71be876cf30125e9bfea197a607ea6945cef7ef28a74676ec23d14378f7ec23964544b6710014140b634941ecab3a5dd7251f9213bfbcff2021b1e3d966e6800007ea6f0d72ec46d2c04c042800e103091d2f5d184d997a10b890b13bf06b1078a4f1822d722891a232102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62ac"
@ -128,7 +127,7 @@ func TestRecoveryMessage_DecodeFromTestnet(t *testing.T) {
buf.ReadB()
require.Equal(t, gio.EOF, buf.Err)
}
*/
func getKeys(t *testing.T, n int) []*privateKey {
privs := make([]*privateKey, 0, n)
for i := 0; i < n; i++ {

View file

@ -1,19 +1,16 @@
package block
import (
"encoding/hex"
"testing"
"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/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/internal/testserdes"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// Test blocks are blocks from mainnet with their corresponding index.
// TODO NEO3.0: Update binary
/*
func TestDecodeBlock1(t *testing.T) {
data, err := getBlockData(1)
require.NoError(t, err)
@ -67,7 +64,7 @@ func TestTrimmedBlock(t *testing.T) {
assert.True(t, trimmedBlock.Transactions[i].Trimmed)
}
}
*/
func newDumbBlock() *Block {
return &Block{
Base: Base{

View file

@ -1340,6 +1340,10 @@ func (bc *Blockchain) verifyHeader(currHeader, prevHeader *block.Header) error {
// verifyTx verifies whether a transaction is bonafide or not.
func (bc *Blockchain) verifyTx(t *transaction.Transaction, block *block.Block) error {
height := bc.BlockHeight()
if t.ValidUntilBlock <= height || t.ValidUntilBlock > height+transaction.MaxValidUntilBlockIncrement {
return errors.Errorf("transaction has expired. ValidUntilBlock = %d, current height = %d", t.ValidUntilBlock, height)
}
if io.GetVarSize(t) > transaction.MaxTransactionSize {
return errors.Errorf("invalid transaction size = %d. It shoud be less then MaxTransactionSize = %d", io.GetVarSize(t), transaction.MaxTransactionSize)
}

View file

@ -7,7 +7,6 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/storage"
"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/io"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -98,7 +97,9 @@ func TestScriptFromWitness(t *testing.T) {
func TestGetHeader(t *testing.T) {
bc := newTestChain(t)
block := bc.newBlock(transaction.NewMinerTX())
tx := transaction.NewMinerTX()
tx.ValidUntilBlock = bc.BlockHeight() + 1
block := bc.newBlock(tx)
err := bc.AddBlock(block)
assert.Nil(t, err)
@ -149,6 +150,8 @@ func TestHasBlock(t *testing.T) {
}
}
//TODO NEO3.0:Update binary
/*
func TestGetTransaction(t *testing.T) {
b1 := getDecodedBlock(t, 1)
block := getDecodedBlock(t, 2)
@ -174,7 +177,7 @@ func TestGetTransaction(t *testing.T) {
assert.NoError(t, bc.persist())
}
}
*/
func TestGetClaimable(t *testing.T) {
bc := newTestChain(t)

View file

@ -96,7 +96,9 @@ func (bc *Blockchain) genBlocks(n int) ([]*block.Block, error) {
lastHash := bc.topBlock.Load().(*block.Block).Hash()
lastIndex := bc.topBlock.Load().(*block.Block).Index
for i := 0; i < n; i++ {
blocks[i] = newBlock(bc.config, uint32(i)+lastIndex+1, lastHash, transaction.NewMinerTXWithNonce(uint32(1234+i)))
minerTx := transaction.NewMinerTXWithNonce(uint32(1234 + i))
minerTx.ValidUntilBlock = lastIndex + uint32(i) + 1
blocks[i] = newBlock(bc.config, uint32(i)+lastIndex+1, lastHash, minerTx)
if err := bc.AddBlock(blocks[i]); err != nil {
return blocks, err
}
@ -167,6 +169,8 @@ func TestCreateBasicChain(t *testing.T) {
const prefix = "../rpc/server/testdata/"
// To make enough GAS.
const numOfEmptyBlocks = 200
// Increase in case if you need more blocks
const validUntilBlock = numOfEmptyBlocks + 1000
// To be incremented after each created transaction to keep chain constant.
var testNonce uint32 = 1
@ -177,12 +181,20 @@ func TestCreateBasicChain(t *testing.T) {
return testNonce
}
// Creates new miner tx with specified validUntilBlock field
nextMinerTx := func(validUntilBlock uint32) *transaction.Transaction {
minerTx := transaction.NewMinerTXWithNonce(getNextNonce())
minerTx.ValidUntilBlock = validUntilBlock
return minerTx
}
var neoAmount = util.Fixed8FromInt64(99999000)
var neoRemainder = util.Fixed8FromInt64(100000000) - neoAmount
bc := newTestChain(t)
// Move almost all NEO to one simple account.
txMoveNeo := transaction.NewContractTX()
txMoveNeo.ValidUntilBlock = validUntilBlock
txMoveNeo.Nonce = getNextNonce()
// use output of issue tx from genesis block as an input
@ -231,8 +243,7 @@ func TestCreateBasicChain(t *testing.T) {
InvocationScript: invoc,
VerificationScript: rawScript,
}}
b := bc.newBlock(transaction.NewMinerTXWithNonce(getNextNonce()), txMoveNeo)
b := bc.newBlock(nextMinerTx(validUntilBlock), txMoveNeo)
require.NoError(t, bc.AddBlock(b))
t.Logf("txMoveNeo: %s", txMoveNeo.Hash().StringLE())
@ -252,6 +263,7 @@ func TestCreateBasicChain(t *testing.T) {
// Make a NEO roundtrip (send to myself) and claim GAS.
txNeoRound := transaction.NewContractTX()
txNeoRound.Nonce = getNextNonce()
txNeoRound.ValidUntilBlock = validUntilBlock
txNeoRound.AddInput(&transaction.Input{
PrevHash: txMoveNeo.Hash(),
PrevIndex: 0,
@ -264,7 +276,7 @@ func TestCreateBasicChain(t *testing.T) {
})
txNeoRound.Data = new(transaction.ContractTX)
require.NoError(t, acc0.SignTx(txNeoRound))
b = bc.newBlock(transaction.NewMinerTXWithNonce(getNextNonce()), txNeoRound)
b = bc.newBlock(nextMinerTx(validUntilBlock), txNeoRound)
require.NoError(t, bc.AddBlock(b))
t.Logf("txNeoRound: %s", txNeoRound.Hash().StringLE())
@ -275,6 +287,7 @@ func TestCreateBasicChain(t *testing.T) {
})
txClaim := transaction.NewClaimTX(claim)
txClaim.Nonce = getNextNonce()
txClaim.ValidUntilBlock = validUntilBlock
txClaim.Data = claim
neoGas, sysGas, err := bc.CalculateClaimable(neoAmount, 1, bc.BlockHeight())
require.NoError(t, err)
@ -286,7 +299,7 @@ func TestCreateBasicChain(t *testing.T) {
Position: 0,
})
require.NoError(t, acc0.SignTx(txClaim))
b = bc.newBlock(transaction.NewMinerTXWithNonce(getNextNonce()), txClaim)
b = bc.newBlock(nextMinerTx(validUntilBlock), txClaim)
require.NoError(t, bc.AddBlock(b))
t.Logf("txClaim: %s", txClaim.Hash().StringLE())
@ -315,6 +328,7 @@ func TestCreateBasicChain(t *testing.T) {
invFee := util.Fixed8FromFloat(100)
txDeploy := transaction.NewInvocationTX(txScript, invFee)
txDeploy.Nonce = getNextNonce()
txDeploy.ValidUntilBlock = validUntilBlock
txDeploy.AddInput(&transaction.Input{
PrevHash: txClaim.Hash(),
PrevIndex: 0,
@ -327,7 +341,7 @@ func TestCreateBasicChain(t *testing.T) {
})
gasOwned -= invFee
require.NoError(t, acc0.SignTx(txDeploy))
b = bc.newBlock(transaction.NewMinerTXWithNonce(getNextNonce()), txDeploy)
b = bc.newBlock(nextMinerTx(validUntilBlock), txDeploy)
require.NoError(t, bc.AddBlock(b))
t.Logf("txDeploy: %s", txDeploy.Hash().StringLE())
@ -337,7 +351,8 @@ func TestCreateBasicChain(t *testing.T) {
txInv := transaction.NewInvocationTX(script.Bytes(), 0)
txInv.Nonce = getNextNonce()
b = bc.newBlock(transaction.NewMinerTXWithNonce(getNextNonce()), txInv)
txInv.ValidUntilBlock = validUntilBlock
b = bc.newBlock(nextMinerTx(validUntilBlock), txInv)
require.NoError(t, bc.AddBlock(b))
t.Logf("txInv: %s", txInv.Hash().StringLE())
@ -345,6 +360,7 @@ func TestCreateBasicChain(t *testing.T) {
require.NoError(t, err)
txNeo0to1 := transaction.NewContractTX()
txNeo0to1.Nonce = getNextNonce()
txNeo0to1.ValidUntilBlock = validUntilBlock
txNeo0to1.Data = new(transaction.ContractTX)
txNeo0to1.AddInput(&transaction.Input{
PrevHash: txNeoRound.Hash(),
@ -362,7 +378,7 @@ func TestCreateBasicChain(t *testing.T) {
})
require.NoError(t, acc0.SignTx(txNeo0to1))
b = bc.newBlock(transaction.NewMinerTXWithNonce(getNextNonce()), txNeo0to1)
b = bc.newBlock(nextMinerTx(validUntilBlock), txNeo0to1)
require.NoError(t, bc.AddBlock(b))
sh := hash.Hash160(avm)
@ -370,15 +386,18 @@ func TestCreateBasicChain(t *testing.T) {
emit.AppCallWithOperationAndArgs(w.BinWriter, sh, "init")
initTx := transaction.NewInvocationTX(w.Bytes(), 0)
initTx.Nonce = getNextNonce()
initTx.ValidUntilBlock = validUntilBlock
transferTx := newNEP5Transfer(sh, sh, priv0.GetScriptHash(), 1000)
transferTx.Nonce = getNextNonce()
transferTx.ValidUntilBlock = validUntilBlock
b = bc.newBlock(transaction.NewMinerTXWithNonce(getNextNonce()), initTx, transferTx)
b = bc.newBlock(nextMinerTx(validUntilBlock), initTx, transferTx)
require.NoError(t, bc.AddBlock(b))
transferTx = newNEP5Transfer(sh, priv0.GetScriptHash(), priv1.GetScriptHash(), 123)
transferTx.Nonce = getNextNonce()
b = bc.newBlock(transaction.NewMinerTXWithNonce(getNextNonce()), transferTx)
transferTx.ValidUntilBlock = validUntilBlock
b = bc.newBlock(nextMinerTx(validUntilBlock), transferTx)
require.NoError(t, bc.AddBlock(b))
if saveChain {
@ -406,6 +425,7 @@ func TestCreateBasicChain(t *testing.T) {
// Make a NEO roundtrip (send to myself) and claim GAS.
txNeoRound = transaction.NewContractTX()
txNeoRound.Nonce = getNextNonce()
txNeoRound.ValidUntilBlock = validUntilBlock
txNeoRound.AddInput(&transaction.Input{
PrevHash: txNeo0to1.Hash(),
PrevIndex: 1,
@ -425,7 +445,7 @@ func TestCreateBasicChain(t *testing.T) {
// 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
blocks = append(blocks, bc.newBlock(), bc.newBlock(transaction.NewMinerTXWithNonce(getNextNonce())))
blocks = append(blocks, bc.newBlock(), bc.newBlock(nextMinerTx(validUntilBlock)))
for i, b := range blocks {
data, err := testserdes.EncodeBinary(b)
require.NoError(t, err)

View file

@ -1,13 +1,7 @@
package transaction
import (
"encoding/hex"
"testing"
"github.com/nspcc-dev/neo-go/pkg/internal/testserdes"
"github.com/stretchr/testify/assert"
)
// TODO NEO3.0: Update binary
/*
func TestEncodeDecodeMiner(t *testing.T) {
// transaction from mainnet a1f219dc6be4c35eca172e65e02d4591045220221b1543f1a4b67b9e9442c264
rawtx := "0000fcd30e22000001e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c60c8000000000000001f72e68b4e39602912106d53b229378a082784b200"
@ -24,3 +18,4 @@ func TestEncodeDecodeMiner(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, rawtx, hex.EncodeToString(data))
}
*/

View file

@ -17,6 +17,9 @@ const (
// MaxTransactionSize is the upper limit size in bytes that a transaction can reach. It is
// set to be 102400.
MaxTransactionSize = 102400
// MaxValidUntilBlockIncrement is the upper increment size of blockhain height in blocs after
// exceeding that a transaction should fail validation. It is set to be 2102400.
MaxValidUntilBlockIncrement = 2102400
)
// Transaction is a process recorded in the NEO blockchain.
@ -30,6 +33,10 @@ type Transaction struct {
// Random number to avoid hash collision.
Nonce uint32
// Maximum blockchain height exceeding which
// transaction should fail verification.
ValidUntilBlock uint32
// Data specific to the type of the transaction.
// This is always a pointer to a <Type>Transaction.
Data TXer
@ -111,6 +118,7 @@ func (t *Transaction) DecodeBinary(br *io.BinReader) {
t.Type = TXType(br.ReadB())
t.Version = uint8(br.ReadB())
t.Nonce = br.ReadU32LE()
t.ValidUntilBlock = br.ReadU32LE()
t.decodeData(br)
br.ReadArray(&t.Attributes)
@ -182,6 +190,7 @@ func (t *Transaction) encodeHashableFields(bw *io.BinWriter) {
bw.WriteB(byte(t.Type))
bw.WriteB(byte(t.Version))
bw.WriteU32LE(t.Nonce)
bw.WriteU32LE(t.ValidUntilBlock)
// Underlying TXer.
if !noData {
@ -257,15 +266,16 @@ func NewTransactionFromBytes(b []byte) (*Transaction, error) {
// transactionJSON is a wrapper for Transaction and
// used for correct marhalling of transaction.Data
type transactionJSON struct {
TxID util.Uint256 `json:"txid"`
Size int `json:"size"`
Type TXType `json:"type"`
Version uint8 `json:"version"`
Nonce uint32 `json:"nonce"`
Attributes []Attribute `json:"attributes"`
Inputs []Input `json:"vin"`
Outputs []Output `json:"vout"`
Scripts []Witness `json:"scripts"`
TxID util.Uint256 `json:"txid"`
Size int `json:"size"`
Type TXType `json:"type"`
Version uint8 `json:"version"`
Nonce uint32 `json:"nonce"`
ValidUntilBlock uint32 `json:"valid_until_block"`
Attributes []Attribute `json:"attributes"`
Inputs []Input `json:"vin"`
Outputs []Output `json:"vout"`
Scripts []Witness `json:"scripts"`
Claims []Input `json:"claims,omitempty"`
PublicKey *keys.PublicKey `json:"pubkey,omitempty"`
@ -279,15 +289,16 @@ type transactionJSON struct {
// MarshalJSON implements json.Marshaler interface.
func (t *Transaction) MarshalJSON() ([]byte, error) {
tx := transactionJSON{
TxID: t.Hash(),
Size: io.GetVarSize(t),
Type: t.Type,
Version: t.Version,
Nonce: t.Nonce,
Attributes: t.Attributes,
Inputs: t.Inputs,
Outputs: t.Outputs,
Scripts: t.Scripts,
TxID: t.Hash(),
Size: io.GetVarSize(t),
Type: t.Type,
Version: t.Version,
Nonce: t.Nonce,
ValidUntilBlock: t.ValidUntilBlock,
Attributes: t.Attributes,
Inputs: t.Inputs,
Outputs: t.Outputs,
Scripts: t.Scripts,
}
switch t.Type {
case ClaimType:
@ -338,6 +349,7 @@ func (t *Transaction) UnmarshalJSON(data []byte) error {
t.Type = tx.Type
t.Version = tx.Version
t.Nonce = tx.Nonce
t.ValidUntilBlock = tx.ValidUntilBlock
t.Attributes = tx.Attributes
t.Inputs = tx.Inputs
t.Outputs = tx.Outputs

View file

@ -20,7 +20,7 @@ func TestGenesisBlockMainNet(t *testing.T) {
// have been changed. Consequently, hash of the genesis block has been changed.
// Update expected genesis block hash for better times.
// Old hash is "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf"
expect := "8c5e44474b2b942286071254fd4bffddd3febd0511b101e566331b5f8f041902"
expect := "cf98b48f81ce3162cdd0883bb0c4cbf3abc105623ba7a61133a776c1e33a2466"
assert.Equal(t, expect, block.Hash().StringLE())
}
@ -47,7 +47,7 @@ func TestUtilityTokenTX(t *testing.T) {
//TODO: After we added Nonce field to transaction.Transaction, UtilityTockenTx hash
// has been changed. Update it for better times.
// Old hash is "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"
expect := "057ea06225860f0f7e69cca1e0052652918629929591b8138a516431be144ba8"
expect := "8dd7d330dd7fc103836409bdcba826d15d88119c7f843357266b253aede72dfb"
assert.Equal(t, expect, UtilityTokenID().StringLE())
}
@ -55,6 +55,6 @@ func TestGoverningTokenTX(t *testing.T) {
//TODO: After we added Nonce field to transaction.Transaction, GoveringTockenTx hash
// has been changed. Update it for better times.
// Old hash is "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b"
expect := "cd3a3b5654465238c3a4ac30eeb1bfd1171378d59b27f7d2e6893ce9d6150825"
expect := "0589624521f631b389197e1a69b1b92db0a45cc70f45c3409dfecc439e99bfa9"
assert.Equal(t, expect, GoverningTokenID().StringLE())
}

View file

@ -24,6 +24,8 @@ const (
defaultDialTimeout = 4 * time.Second
defaultRequestTimeout = 4 * time.Second
defaultClientVersion = "2.0"
// number of blocks after which cache is expired
cacheTimeout = 100
)
// Client represents the middleman for executing JSON RPC calls
@ -40,6 +42,7 @@ type Client struct {
wif *keys.WIF
balancerMu *sync.Mutex
balancer request.BalanceGetter
cache cache
}
// Options defines options for the RPC client.
@ -57,6 +60,18 @@ type Options struct {
Version string
}
// cache stores cache values for the RPC client methods
type cache struct {
calculateValidUntilBlock calculateValidUntilBlockCache
}
// calculateValidUntilBlockCache stores cached number of validators and
// cache expiration value in blocks
type calculateValidUntilBlockCache struct {
validatorsCount uint32
expiresAt uint32
}
// New returns a new Client ready to use.
func New(ctx context.Context, endpoint string, opts Options) (*Client, error) {
url, err := url.Parse(endpoint)

View file

@ -490,6 +490,13 @@ func (c *Client) TransferAsset(asset util.Uint256, address string, amount util.F
if rawTx, err = request.CreateRawContractTransaction(txParams); err != nil {
return resp, errors.Wrap(err, "failed to create raw transaction")
}
validUntilBlock, err := c.CalculateValidUntilBlock()
if err != nil {
return resp, errors.Wrap(err, "failed to add validUntilBlock to raw transaction")
}
rawTx.ValidUntilBlock = validUntilBlock
if err = c.SendRawTransaction(rawTx); err != nil {
return resp, errors.Wrap(err, "failed to send raw transaction")
}
@ -504,6 +511,12 @@ func (c *Client) SignAndPushInvocationTx(script []byte, acc *wallet.Account, sys
var err error
tx := transaction.NewInvocationTX(script, sysfee)
validUntilBlock, err := c.CalculateValidUntilBlock()
if err != nil {
return txHash, errors.Wrap(err, "failed to add validUntilBlock to transaction")
}
tx.ValidUntilBlock = validUntilBlock
gas := sysfee + netfee
if gas > 0 {
@ -545,3 +558,33 @@ func (c *Client) ValidateAddress(address string) error {
}
return nil
}
// CalculateValidUntilBlock calculates ValidUntilBlock field for tx as
// current blockchain height + number of validators. Number of validators
// is the length of blockchain validators list got from GetValidators()
// method. Validators count is being cached and updated every 100 blocks.
func (c *Client) CalculateValidUntilBlock() (uint32, error) {
var (
result uint32
validatorsCount uint32
)
blockCount, err := c.GetBlockCount()
if err != nil {
return result, errors.Wrapf(err, "cannot get block count")
}
if c.cache.calculateValidUntilBlock.expiresAt > blockCount {
validatorsCount = c.cache.calculateValidUntilBlock.validatorsCount
} else {
validators, err := c.GetValidators()
if err != nil {
return result, errors.Wrapf(err, "cannot get validators")
}
validatorsCount = uint32(len(validators))
c.cache.calculateValidUntilBlock = calculateValidUntilBlockCache{
validatorsCount: validatorsCount,
expiresAt: blockCount + cacheTimeout,
}
}
return blockCount + validatorsCount, nil
}

View file

@ -8,6 +8,8 @@ import (
"net/http/httptest"
"testing"
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
"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/transaction"
@ -37,7 +39,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
invoke: func(c *Client) (interface{}, error) {
return c.GetAccountState("")
},
serverResponse: `{"jsonrpc":"2.0","id": 1,"result":{"version":0,"script_hash":"0x1179716da2e9523d153a35fb3ad10c561b1e5b1a","frozen":false,"votes":[],"balances":[{"asset":"0xcd3a3b5654465238c3a4ac30eeb1bfd1171378d59b27f7d2e6893ce9d6150825","value":"94"}]}}`,
serverResponse: `{"jsonrpc":"2.0","id": 1,"result":{"version":0,"script_hash":"0x1179716da2e9523d153a35fb3ad10c561b1e5b1a","frozen":false,"votes":[],"balances":[{"asset":"0x0589624521f631b389197e1a69b1b92db0a45cc70f45c3409dfecc439e99bfa9","value":"94"}]}}`,
result: func(c *Client) interface{} {
scriptHash, err := util.Uint160DecodeStringLE("1179716da2e9523d153a35fb3ad10c561b1e5b1a")
if err != nil {
@ -96,7 +98,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
invoke: func(c *Client) (interface{}, error) {
return c.GetAssetState(util.Uint256{})
},
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":"0xcd3a3b5654465238c3a4ac30eeb1bfd1171378d59b27f7d2e6893ce9d6150825","type":0,"name":"NEO","amount":"100000000","available":"100000000","precision":0,"owner":"00","admin":"Abf2qMs1pzQb8kYk9RuxtUb9jtRKJVuBJt","issuer":"AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM","expiration":4000000,"is_frozen":false}}`,
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":"0x0589624521f631b389197e1a69b1b92db0a45cc70f45c3409dfecc439e99bfa9","type":0,"name":"NEO","amount":"100000000","available":"100000000","precision":0,"owner":"00","admin":"Abf2qMs1pzQb8kYk9RuxtUb9jtRKJVuBJt","issuer":"AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM","expiration":4000000,"is_frozen":false}}`,
result: func(c *Client) interface{} {
return &result.AssetState{
ID: core.GoverningTokenID(),
@ -134,45 +136,45 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
{
name: "byIndex_positive",
invoke: func(c *Client) (interface{}, error) {
return c.GetBlockByIndex(1)
return c.GetBlockByIndex(5)
},
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"00000000999086db552ba8f84734bddca55b25a8d3d8c5f866f941209169c38d35376e99b29ffa96224227f5e033c9a291bceef2724429d596c3a6944cafd6995fdb6dcbe013dd5b010000004ded49fea284b451be48d3a3f5d10013ab9ffee489706078714f1ea201c340356a91d94e398170e47447d6a0f60aa5470e209782a5452403115a49166db3e1c4a3898122db19f779c30f8ccd0b7d401acdf71eda340655e4ae5237a64961bf4034dd47955e5a71627dafc39dd92999140e9eaeec6b11dbb2b313efa3f1093ed915b4455e199c69ec53778f94ffc236b92f8b97fff97a1f6bbb3770c0c0b3844a40fbe743bd5c90b2f5255e0b073281d7aeb2fb516572f36bec8446bcc37ac755cbf10d08b16c95644db1b2dddc2df5daa377880b20198fc7b967ac6e76474b22df8b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae0100004ded49fe00000000"}`,
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"00000000a78c4548ad5fd899f4980cffcc8610f4dc22037de3f1fd374cc4384e1eb24e85f0bd34849ad1bda48acd6b9c9401654f9e6499f95dab85923de66c3b1242d59c858e955e050000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd040140445e8de1ba402cab0bffedc32840b3587c8f6b272c02ea2b4a609419fbcb85a3cf5cd183ea7d28788eb19a12265be1d2f43f7986de66c8d8585d66825a0701fc40d935dfb83310d3433a7afc0bbb15f4c0686a624734cee6f6b98d5d95e660401c5b35c7cfd802fa82759aab288373ad894d82056d29109e6142d8c1397f60706f4076e9fd7bef3b9a8ce12904414cc55293161bcb536a4939200dd3c586c4d60ded565780d307598b8dcf4eebb64f53cc9fc0c381d47e58b7cec1b9392097a2b3ec407b03a25d83d429810b7a929f48b8125d3bfff5982f876c0dbd1d9dbbf08534d3235a4709c7f779449ed865ca1d2e29729c0210174782869a09c2b821bd15fda18b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae010000d50400000500000000000000"}`,
result: func(c *Client) interface{} { return &block.Block{} },
check: func(t *testing.T, c *Client, result interface{}) {
res, ok := result.(*block.Block)
require.True(t, ok)
assert.Equal(t, uint32(0), res.Version)
assert.Equal(t, "e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c", res.Hash().StringLE())
assert.Equal(t, "996e37358dc369912041f966f8c5d8d3a8255ba5dcbd3447f8a82b55db869099", res.PrevHash.StringLE())
assert.Equal(t, "cb6ddb5f99d6af4c94a6c396d5294472f2eebc91a2c933e0f527422296fa9fb2", res.MerkleRoot.StringLE())
assert.Equal(t, "a928e6e394bbc8ebb02b88fa14efb2860c9de376b4809ba078e7e47ca9a77af9", res.Hash().StringLE())
assert.Equal(t, "854eb21e4e38c44c37fdf1e37d0322dcf41086ccff0c98f499d85fad48458ca7", res.PrevHash.StringLE())
assert.Equal(t, "9cd542123b6ce63d9285ab5df999649e4f6501949c6bcd8aa4bdd19a8434bdf0", res.MerkleRoot.StringLE())
assert.Equal(t, 1, len(res.Transactions))
assert.Equal(t, "cb6ddb5f99d6af4c94a6c396d5294472f2eebc91a2c933e0f527422296fa9fb2", res.Transactions[0].Hash().StringLE())
assert.Equal(t, "9cd542123b6ce63d9285ab5df999649e4f6501949c6bcd8aa4bdd19a8434bdf0", res.Transactions[0].Hash().StringLE())
},
},
{
name: "byIndex_verbose_positive",
invoke: func(c *Client) (i interface{}, err error) {
return c.GetBlockByIndexVerbose(1)
return c.GetBlockByIndexVerbose(5)
},
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"hash":"0xe93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c","size":452,"version":0,"nextblockhash":"0xcc37d5bc460e72c9423015cb8d579c13e7b03b93bfaa1a23cf4fa777988e035f","previousblockhash":"0x996e37358dc369912041f966f8c5d8d3a8255ba5dcbd3447f8a82b55db869099","merkleroot":"0xcb6ddb5f99d6af4c94a6c396d5294472f2eebc91a2c933e0f527422296fa9fb2","time":1541215200,"index":1,"nonce":"51b484a2fe49ed4d","nextconsensus":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","confirmations":10534,"script":{"invocation":"40356a91d94e398170e47447d6a0f60aa5470e209782a5452403115a49166db3e1c4a3898122db19f779c30f8ccd0b7d401acdf71eda340655e4ae5237a64961bf4034dd47955e5a71627dafc39dd92999140e9eaeec6b11dbb2b313efa3f1093ed915b4455e199c69ec53778f94ffc236b92f8b97fff97a1f6bbb3770c0c0b3844a40fbe743bd5c90b2f5255e0b073281d7aeb2fb516572f36bec8446bcc37ac755cbf10d08b16c95644db1b2dddc2df5daa377880b20198fc7b967ac6e76474b22df","verification":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae"},"tx":[{"txid":"0xcb6ddb5f99d6af4c94a6c396d5294472f2eebc91a2c933e0f527422296fa9fb2","size":10,"type":"MinerTransaction","version":0,"attributes":[],"vin":[],"vout":[],"scripts":[],"sys_fee":"0","net_fee":"0","nonce":4266257741}]}}`,
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"hash":"0xa928e6e394bbc8ebb02b88fa14efb2860c9de376b4809ba078e7e47ca9a77af9","size":523,"version":0,"nextblockhash":"0x5ff4068d996cbefb6fb6e36f6c8085a79f7ab28cc3149b6f49a55cf97fa4b513","previousblockhash":"0x854eb21e4e38c44c37fdf1e37d0322dcf41086ccff0c98f499d85fad48458ca7","merkleroot":"0x9cd542123b6ce63d9285ab5df999649e4f6501949c6bcd8aa4bdd19a8434bdf0","time":1586859653,"index":5,"nonce":"0000000000000457","nextconsensus":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","confirmations":203,"script":{"invocation":"40445e8de1ba402cab0bffedc32840b3587c8f6b272c02ea2b4a609419fbcb85a3cf5cd183ea7d28788eb19a12265be1d2f43f7986de66c8d8585d66825a0701fc40d935dfb83310d3433a7afc0bbb15f4c0686a624734cee6f6b98d5d95e660401c5b35c7cfd802fa82759aab288373ad894d82056d29109e6142d8c1397f60706f4076e9fd7bef3b9a8ce12904414cc55293161bcb536a4939200dd3c586c4d60ded565780d307598b8dcf4eebb64f53cc9fc0c381d47e58b7cec1b9392097a2b3ec407b03a25d83d429810b7a929f48b8125d3bfff5982f876c0dbd1d9dbbf08534d3235a4709c7f779449ed865ca1d2e29729c0210174782869a09c2b821bd15fda1","verification":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae"},"tx":[{"sys_fee":"0","net_fee":"0","txid":"0x9cd542123b6ce63d9285ab5df999649e4f6501949c6bcd8aa4bdd19a8434bdf0","size":14,"type":"MinerTransaction","version":0,"nonce":1237,"valid_until_block":5,"attributes":[],"vin":[],"vout":[],"scripts":[]}]}}`,
result: func(c *Client) interface{} {
hash, err := util.Uint256DecodeStringLE("e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c")
hash, err := util.Uint256DecodeStringLE("a928e6e394bbc8ebb02b88fa14efb2860c9de376b4809ba078e7e47ca9a77af9")
if err != nil {
panic(err)
}
nextBlockHash, err := util.Uint256DecodeStringLE("cc37d5bc460e72c9423015cb8d579c13e7b03b93bfaa1a23cf4fa777988e035f")
nextBlockHash, err := util.Uint256DecodeStringLE("5ff4068d996cbefb6fb6e36f6c8085a79f7ab28cc3149b6f49a55cf97fa4b513")
if err != nil {
panic(err)
}
prevBlockHash, err := util.Uint256DecodeStringLE("996e37358dc369912041f966f8c5d8d3a8255ba5dcbd3447f8a82b55db869099")
prevBlockHash, err := util.Uint256DecodeStringLE("854eb21e4e38c44c37fdf1e37d0322dcf41086ccff0c98f499d85fad48458ca7")
if err != nil {
panic(err)
}
merkleRoot, err := util.Uint256DecodeStringLE("cb6ddb5f99d6af4c94a6c396d5294472f2eebc91a2c933e0f527422296fa9fb2")
merkleRoot, err := util.Uint256DecodeStringLE("9cd542123b6ce63d9285ab5df999649e4f6501949c6bcd8aa4bdd19a8434bdf0")
if err != nil {
panic(err)
}
invScript, err := hex.DecodeString("40356a91d94e398170e47447d6a0f60aa5470e209782a5452403115a49166db3e1c4a3898122db19f779c30f8ccd0b7d401acdf71eda340655e4ae5237a64961bf4034dd47955e5a71627dafc39dd92999140e9eaeec6b11dbb2b313efa3f1093ed915b4455e199c69ec53778f94ffc236b92f8b97fff97a1f6bbb3770c0c0b3844a40fbe743bd5c90b2f5255e0b073281d7aeb2fb516572f36bec8446bcc37ac755cbf10d08b16c95644db1b2dddc2df5daa377880b20198fc7b967ac6e76474b22df")
invScript, err := hex.DecodeString("40445e8de1ba402cab0bffedc32840b3587c8f6b272c02ea2b4a609419fbcb85a3cf5cd183ea7d28788eb19a12265be1d2f43f7986de66c8d8585d66825a0701fc40d935dfb83310d3433a7afc0bbb15f4c0686a624734cee6f6b98d5d95e660401c5b35c7cfd802fa82759aab288373ad894d82056d29109e6142d8c1397f60706f4076e9fd7bef3b9a8ce12904414cc55293161bcb536a4939200dd3c586c4d60ded565780d307598b8dcf4eebb64f53cc9fc0c381d47e58b7cec1b9392097a2b3ec407b03a25d83d429810b7a929f48b8125d3bfff5982f876c0dbd1d9dbbf08534d3235a4709c7f779449ed865ca1d2e29729c0210174782869a09c2b821bd15fda1")
if err != nil {
panic(err)
}
@ -180,21 +182,22 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
if err != nil {
panic(err)
}
tx := transaction.NewMinerTXWithNonce(4266257741)
tx := transaction.NewMinerTXWithNonce(1237)
tx.ValidUntilBlock = 5
// Update hashes for correct result comparison.
_ = tx.Hash()
return &result.Block{
Hash: hash,
Size: 452,
Size: 523,
Version: 0,
NextBlockHash: &nextBlockHash,
PreviousBlockHash: prevBlockHash,
MerkleRoot: merkleRoot,
Time: 1541215200,
Index: 1,
Nonce: "51b484a2fe49ed4d",
Time: 1586859653,
Index: 5,
Nonce: "0000000000000457",
NextConsensus: "AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU",
Confirmations: 10534,
Confirmations: 203,
Script: transaction.Witness{
InvocationScript: invScript,
VerificationScript: verifScript,
@ -212,53 +215,53 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
{
name: "byHash_positive",
invoke: func(c *Client) (interface{}, error) {
hash, err := util.Uint256DecodeStringLE("e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c")
hash, err := util.Uint256DecodeStringLE("f97aa7a97ce4e778a09b80b476e39d0c86b2ef14fa882bb0ebc8bb94e3e628a9")
if err != nil {
panic(err)
}
return c.GetBlockByHash(hash)
},
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"00000000999086db552ba8f84734bddca55b25a8d3d8c5f866f941209169c38d35376e99b29ffa96224227f5e033c9a291bceef2724429d596c3a6944cafd6995fdb6dcbe013dd5b010000004ded49fea284b451be48d3a3f5d10013ab9ffee489706078714f1ea201c340356a91d94e398170e47447d6a0f60aa5470e209782a5452403115a49166db3e1c4a3898122db19f779c30f8ccd0b7d401acdf71eda340655e4ae5237a64961bf4034dd47955e5a71627dafc39dd92999140e9eaeec6b11dbb2b313efa3f1093ed915b4455e199c69ec53778f94ffc236b92f8b97fff97a1f6bbb3770c0c0b3844a40fbe743bd5c90b2f5255e0b073281d7aeb2fb516572f36bec8446bcc37ac755cbf10d08b16c95644db1b2dddc2df5daa377880b20198fc7b967ac6e76474b22df8b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae0100004ded49fe00000000"}`,
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"00000000a78c4548ad5fd899f4980cffcc8610f4dc22037de3f1fd374cc4384e1eb24e85f0bd34849ad1bda48acd6b9c9401654f9e6499f95dab85923de66c3b1242d59c858e955e050000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd040140445e8de1ba402cab0bffedc32840b3587c8f6b272c02ea2b4a609419fbcb85a3cf5cd183ea7d28788eb19a12265be1d2f43f7986de66c8d8585d66825a0701fc40d935dfb83310d3433a7afc0bbb15f4c0686a624734cee6f6b98d5d95e660401c5b35c7cfd802fa82759aab288373ad894d82056d29109e6142d8c1397f60706f4076e9fd7bef3b9a8ce12904414cc55293161bcb536a4939200dd3c586c4d60ded565780d307598b8dcf4eebb64f53cc9fc0c381d47e58b7cec1b9392097a2b3ec407b03a25d83d429810b7a929f48b8125d3bfff5982f876c0dbd1d9dbbf08534d3235a4709c7f779449ed865ca1d2e29729c0210174782869a09c2b821bd15fda18b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae010000d50400000500000000000000"}`,
result: func(c *Client) interface{} { return &block.Block{} },
check: func(t *testing.T, c *Client, result interface{}) {
res, ok := result.(*block.Block)
require.True(t, ok)
assert.Equal(t, uint32(0), res.Version)
assert.Equal(t, "e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c", res.Hash().StringLE())
assert.Equal(t, "996e37358dc369912041f966f8c5d8d3a8255ba5dcbd3447f8a82b55db869099", res.PrevHash.StringLE())
assert.Equal(t, "cb6ddb5f99d6af4c94a6c396d5294472f2eebc91a2c933e0f527422296fa9fb2", res.MerkleRoot.StringLE())
assert.Equal(t, "a928e6e394bbc8ebb02b88fa14efb2860c9de376b4809ba078e7e47ca9a77af9", res.Hash().StringLE())
assert.Equal(t, "854eb21e4e38c44c37fdf1e37d0322dcf41086ccff0c98f499d85fad48458ca7", res.PrevHash.StringLE())
assert.Equal(t, "9cd542123b6ce63d9285ab5df999649e4f6501949c6bcd8aa4bdd19a8434bdf0", res.MerkleRoot.StringLE())
assert.Equal(t, 1, len(res.Transactions))
assert.Equal(t, "cb6ddb5f99d6af4c94a6c396d5294472f2eebc91a2c933e0f527422296fa9fb2", res.Transactions[0].Hash().StringLE())
assert.Equal(t, "9cd542123b6ce63d9285ab5df999649e4f6501949c6bcd8aa4bdd19a8434bdf0", res.Transactions[0].Hash().StringLE())
},
},
{
name: "byHash_verbose_positive",
invoke: func(c *Client) (i interface{}, err error) {
hash, err := util.Uint256DecodeStringLE("e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c")
hash, err := util.Uint256DecodeStringLE("f97aa7a97ce4e778a09b80b476e39d0c86b2ef14fa882bb0ebc8bb94e3e628a9")
if err != nil {
panic(err)
}
return c.GetBlockByHashVerbose(hash)
},
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"hash":"0xe93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c","size":452,"version":0,"nextblockhash":"0xcc37d5bc460e72c9423015cb8d579c13e7b03b93bfaa1a23cf4fa777988e035f","previousblockhash":"0x996e37358dc369912041f966f8c5d8d3a8255ba5dcbd3447f8a82b55db869099","merkleroot":"0xcb6ddb5f99d6af4c94a6c396d5294472f2eebc91a2c933e0f527422296fa9fb2","time":1541215200,"index":1,"nonce":"51b484a2fe49ed4d","nextconsensus":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","confirmations":10534,"script":{"invocation":"40356a91d94e398170e47447d6a0f60aa5470e209782a5452403115a49166db3e1c4a3898122db19f779c30f8ccd0b7d401acdf71eda340655e4ae5237a64961bf4034dd47955e5a71627dafc39dd92999140e9eaeec6b11dbb2b313efa3f1093ed915b4455e199c69ec53778f94ffc236b92f8b97fff97a1f6bbb3770c0c0b3844a40fbe743bd5c90b2f5255e0b073281d7aeb2fb516572f36bec8446bcc37ac755cbf10d08b16c95644db1b2dddc2df5daa377880b20198fc7b967ac6e76474b22df","verification":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae"},"tx":[{"txid":"0xcb6ddb5f99d6af4c94a6c396d5294472f2eebc91a2c933e0f527422296fa9fb2","size":10,"type":"MinerTransaction","version":0,"attributes":[],"vin":[],"vout":[],"scripts":[],"sys_fee":"0","net_fee":"0","nonce":4266257741}]}}`,
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"hash":"0xa928e6e394bbc8ebb02b88fa14efb2860c9de376b4809ba078e7e47ca9a77af9","size":523,"version":0,"nextblockhash":"0x5ff4068d996cbefb6fb6e36f6c8085a79f7ab28cc3149b6f49a55cf97fa4b513","previousblockhash":"0x854eb21e4e38c44c37fdf1e37d0322dcf41086ccff0c98f499d85fad48458ca7","merkleroot":"0x9cd542123b6ce63d9285ab5df999649e4f6501949c6bcd8aa4bdd19a8434bdf0","time":1586859653,"index":5,"nonce":"0000000000000457","nextconsensus":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","confirmations":203,"script":{"invocation":"40445e8de1ba402cab0bffedc32840b3587c8f6b272c02ea2b4a609419fbcb85a3cf5cd183ea7d28788eb19a12265be1d2f43f7986de66c8d8585d66825a0701fc40d935dfb83310d3433a7afc0bbb15f4c0686a624734cee6f6b98d5d95e660401c5b35c7cfd802fa82759aab288373ad894d82056d29109e6142d8c1397f60706f4076e9fd7bef3b9a8ce12904414cc55293161bcb536a4939200dd3c586c4d60ded565780d307598b8dcf4eebb64f53cc9fc0c381d47e58b7cec1b9392097a2b3ec407b03a25d83d429810b7a929f48b8125d3bfff5982f876c0dbd1d9dbbf08534d3235a4709c7f779449ed865ca1d2e29729c0210174782869a09c2b821bd15fda1","verification":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae"},"tx":[{"sys_fee":"0","net_fee":"0","txid":"0x9cd542123b6ce63d9285ab5df999649e4f6501949c6bcd8aa4bdd19a8434bdf0","size":14,"type":"MinerTransaction","version":0,"nonce":1237,"valid_until_block":5,"attributes":[],"vin":[],"vout":[],"scripts":[]}]}}`,
result: func(c *Client) interface{} {
hash, err := util.Uint256DecodeStringLE("e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c")
hash, err := util.Uint256DecodeStringLE("a928e6e394bbc8ebb02b88fa14efb2860c9de376b4809ba078e7e47ca9a77af9")
if err != nil {
panic(err)
}
nextBlockHash, err := util.Uint256DecodeStringLE("cc37d5bc460e72c9423015cb8d579c13e7b03b93bfaa1a23cf4fa777988e035f")
nextBlockHash, err := util.Uint256DecodeStringLE("5ff4068d996cbefb6fb6e36f6c8085a79f7ab28cc3149b6f49a55cf97fa4b513")
if err != nil {
panic(err)
}
prevBlockHash, err := util.Uint256DecodeStringLE("996e37358dc369912041f966f8c5d8d3a8255ba5dcbd3447f8a82b55db869099")
prevBlockHash, err := util.Uint256DecodeStringLE("854eb21e4e38c44c37fdf1e37d0322dcf41086ccff0c98f499d85fad48458ca7")
if err != nil {
panic(err)
}
merkleRoot, err := util.Uint256DecodeStringLE("cb6ddb5f99d6af4c94a6c396d5294472f2eebc91a2c933e0f527422296fa9fb2")
merkleRoot, err := util.Uint256DecodeStringLE("9cd542123b6ce63d9285ab5df999649e4f6501949c6bcd8aa4bdd19a8434bdf0")
if err != nil {
panic(err)
}
invScript, err := hex.DecodeString("40356a91d94e398170e47447d6a0f60aa5470e209782a5452403115a49166db3e1c4a3898122db19f779c30f8ccd0b7d401acdf71eda340655e4ae5237a64961bf4034dd47955e5a71627dafc39dd92999140e9eaeec6b11dbb2b313efa3f1093ed915b4455e199c69ec53778f94ffc236b92f8b97fff97a1f6bbb3770c0c0b3844a40fbe743bd5c90b2f5255e0b073281d7aeb2fb516572f36bec8446bcc37ac755cbf10d08b16c95644db1b2dddc2df5daa377880b20198fc7b967ac6e76474b22df")
invScript, err := hex.DecodeString("40445e8de1ba402cab0bffedc32840b3587c8f6b272c02ea2b4a609419fbcb85a3cf5cd183ea7d28788eb19a12265be1d2f43f7986de66c8d8585d66825a0701fc40d935dfb83310d3433a7afc0bbb15f4c0686a624734cee6f6b98d5d95e660401c5b35c7cfd802fa82759aab288373ad894d82056d29109e6142d8c1397f60706f4076e9fd7bef3b9a8ce12904414cc55293161bcb536a4939200dd3c586c4d60ded565780d307598b8dcf4eebb64f53cc9fc0c381d47e58b7cec1b9392097a2b3ec407b03a25d83d429810b7a929f48b8125d3bfff5982f876c0dbd1d9dbbf08534d3235a4709c7f779449ed865ca1d2e29729c0210174782869a09c2b821bd15fda1")
if err != nil {
panic(err)
}
@ -266,21 +269,22 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
if err != nil {
panic(err)
}
tx := transaction.NewMinerTXWithNonce(4266257741)
tx := transaction.NewMinerTXWithNonce(1237)
tx.ValidUntilBlock = 5
// Update hashes for correct result comparison.
_ = tx.Hash()
return &result.Block{
Hash: hash,
Size: 452,
Size: 523,
Version: 0,
NextBlockHash: &nextBlockHash,
PreviousBlockHash: prevBlockHash,
MerkleRoot: merkleRoot,
Time: 1541215200,
Index: 1,
Nonce: "51b484a2fe49ed4d",
Time: 1586859653,
Index: 5,
Nonce: "0000000000000457",
NextConsensus: "AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU",
Confirmations: 10534,
Confirmations: 203,
Script: transaction.Witness{
InvocationScript: invScript,
VerificationScript: verifScript,
@ -606,19 +610,19 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
{
name: "positive",
invoke: func(c *Client) (i interface{}, err error) {
hash, err := util.Uint256DecodeStringLE("cb6ddb5f99d6af4c94a6c396d5294472f2eebc91a2c933e0f527422296fa9fb2")
hash, err := util.Uint256DecodeStringLE("0b698b4ac68fc3206e65868e8f51ea5ac29e92b5faf9e79562cd57fc744d47c5")
if err != nil {
panic(err)
}
return c.GetRawTransaction(hash)
},
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"00004ded49fe00000000"}`,
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"00001dac2b7c0100000000000000"}`,
result: func(c *Client) interface{} { return &transaction.Transaction{} },
check: func(t *testing.T, c *Client, result interface{}) {
res, ok := result.(*transaction.Transaction)
require.True(t, ok)
assert.Equal(t, uint8(0), res.Version)
assert.Equal(t, "cb6ddb5f99d6af4c94a6c396d5294472f2eebc91a2c933e0f527422296fa9fb2", res.Hash().StringLE())
assert.Equal(t, "0b698b4ac68fc3206e65868e8f51ea5ac29e92b5faf9e79562cd57fc744d47c5", res.Hash().StringBE())
assert.Equal(t, transaction.MinerType, res.Type)
assert.Equal(t, false, res.Trimmed)
},
@ -626,19 +630,20 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
{
name: "verbose_positive",
invoke: func(c *Client) (interface{}, error) {
hash, err := util.Uint256DecodeStringLE("cb6ddb5f99d6af4c94a6c396d5294472f2eebc91a2c933e0f527422296fa9fb2")
hash, err := util.Uint256DecodeStringLE("0b698b4ac68fc3206e65868e8f51ea5ac29e92b5faf9e79562cd57fc744d47c5")
if err != nil {
panic(err)
}
return c.GetRawTransactionVerbose(hash)
},
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"nonce":4266257741,"type":"MinerTransaction","version":0,"attributes":[],"vin":[],"vout":[],"scripts":[],"txid":"0xcb6ddb5f99d6af4c94a6c396d5294472f2eebc91a2c933e0f527422296fa9fb2","size":10,"sys_fee":"0","net_fee":"0","blockhash":"0xe93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c","confirmations":20875,"blocktime":1541215200}}`,
serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"sys_fee":"0","net_fee":"0","blockhash":"0x77007ec4921dd78e91c26bee9c14b49148ae08140f698accea49ecc279e68435","confirmations":210,"blocktime":1468595301,"txid":"0xc5474d74fc57cd6295e7f9fab5929ec25aea518f8e86656e20c38fc64a8b690b","size":14,"type":"MinerTransaction","version":0,"nonce":2083236893,"valid_until_block":1,"attributes":[],"vin":[],"vout":[],"scripts":[]}}`,
result: func(c *Client) interface{} {
blockHash, err := util.Uint256DecodeStringLE("e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c")
blockHash, err := util.Uint256DecodeStringLE("77007ec4921dd78e91c26bee9c14b49148ae08140f698accea49ecc279e68435")
if err != nil {
panic(err)
}
tx := transaction.NewMinerTXWithNonce(4266257741)
tx := transaction.NewMinerTXWithNonce(2083236893)
tx.ValidUntilBlock = 1
// Update hashes for correct result comparison.
_ = tx.Hash()
@ -648,8 +653,8 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
SysFee: 0,
NetFee: 0,
Blockhash: blockHash,
Confirmations: 20875,
Timestamp: uint32(1541215200),
Confirmations: 210,
Timestamp: uint32(1468595301),
},
}
},
@ -1438,3 +1443,50 @@ func requestHandler(t *testing.T, w http.ResponseWriter, resp string) {
t.Fatalf("Error encountered while encoding response: %s", err.Error())
}
}
func TestCalculateValidUntilBlock(t *testing.T) {
var (
getBlockCountCalled int
getValidatorsCalled int
)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
r := request.NewIn()
err := r.DecodeData(req.Body)
if err != nil {
t.Fatalf("Cannot decode request body: %s", req.Body)
}
var response string
switch r.Method {
case "getblockcount":
getBlockCountCalled++
response = `{"jsonrpc":"2.0","id":1,"result":50}`
case "getvalidators":
getValidatorsCalled++
response = `{"id":1,"jsonrpc":"2.0","result":[{"publickey":"02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2","votes":"0","active":true},{"publickey":"02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e","votes":"0","active":true},{"publickey":"03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699","votes":"0","active":true},{"publickey":"02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62","votes":"0","active":true}]}`
default:
t.Fatalf("Bad request method: %s", r.Method)
}
requestHandler(t, w, response)
}))
defer srv.Close()
endpoint := srv.URL
opts := Options{}
c, err := New(context.TODO(), endpoint, opts)
if err != nil {
t.Fatal(err)
}
validUntilBlock, err := c.CalculateValidUntilBlock()
assert.NoError(t, err)
assert.Equal(t, uint32(54), validUntilBlock)
assert.Equal(t, 1, getBlockCountCalled)
assert.Equal(t, 1, getValidatorsCalled)
// check, whether caching is working
validUntilBlock, err = c.CalculateValidUntilBlock()
assert.NoError(t, err)
assert.Equal(t, uint32(54), validUntilBlock)
assert.Equal(t, 2, getBlockCountCalled)
assert.Equal(t, 1, getValidatorsCalled)
}

View file

@ -49,14 +49,14 @@ var rpcTestCases = map[string][]rpcTestCase{
"getapplicationlog": {
{
name: "positive",
params: `["0d77a6c348097c4b29fd9d0fe8657c621bc7d804034c71272e3c4f13775138f2"]`,
params: `["e5a6be3cd796e2284a55ebb2061f85d3f199263bbf659dbd5b670a6506e7a4a0"]`,
result: func(e *executor) interface{} { return &result.ApplicationLog{} },
check: func(t *testing.T, e *executor, acc interface{}) {
res, ok := acc.(*result.ApplicationLog)
require.True(t, ok)
expectedTxHash, err := util.Uint256DecodeStringLE("0d77a6c348097c4b29fd9d0fe8657c621bc7d804034c71272e3c4f13775138f2")
expectedTxHash, err := util.Uint256DecodeStringLE("e5a6be3cd796e2284a55ebb2061f85d3f199263bbf659dbd5b670a6506e7a4a0")
require.NoError(t, err)
assert.Equal(t, expectedTxHash, res.TxHash)
assert.Equal(t, 1, len(res.Executions))
@ -251,7 +251,7 @@ var rpcTestCases = map[string][]rpcTestCase{
"getassetstate": {
{
name: "positive",
params: `["057ea06225860f0f7e69cca1e0052652918629929591b8138a516431be144ba8"]`,
params: `["8dd7d330dd7fc103836409bdcba826d15d88119c7f843357266b253aede72dfb"]`,
result: func(e *executor) interface{} { return &result.AssetState{} },
check: func(t *testing.T, e *executor, as interface{}) {
res, ok := as.(*result.AssetState)
@ -405,25 +405,25 @@ var rpcTestCases = map[string][]rpcTestCase{
"getblockheader": {
{
name: "positive, no verbose",
params: `["7c32645dab0d87cfaddd5db053e2430c669f807e9efc2b91d1f50a824893352f"]`,
params: `["02b9e6f634578f34c6026f1676e25aa04f58889a320fba8bc632c6fe48c26cf1"]`,
result: func(e *executor) interface{} {
expected := "000000002534685cc322d339f957ea368a654bf30b834be4cac0b8441375cce2a37630625507db78d2a2f3130c6073bd68f57202248fdc8966fa8706e88eb0fc61df74085384945e010000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd040140b622b3bdddb8c5e52ae8b4bce5665eb6e2aca950ba72386ea0d37e364af2c7fc40f009c47e1a2140bee90d1e2f81c705d6f2499fe6230b27d1f225c45f38d3c440ec01e743024c2c63dccb2ca4a555eeadb2e6115fe6bc42a8d5c17093828e4ea779b36c6d1535c70c047c709183fc1c93139153291dd0edb614dd3e17d67038dd400f7635816214254b7fba0bb480e2a0ab149c84854adcb542124e67f4cedbf551690f8048271c3f05bbe50f576dcbaf3607afffa2551480cdc24908df0fd47c60408d724d6cfb9bf99e38dc42974f084d110057d3f23a04f5bbf99f5712dad17ae842416bb3e30fee034a317280565cb772f8a61fd09cb05e76db27c5fc7722819f8b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae00"
expected := "000000009456b8c7f89bdfe012a30a2be9af5218e048ae7372115ce3e39cc847c01e9e7f9cffa26c112eb147a995520e47afbc45a192d9bf1a8e9b8f80497e5d92c4e9f2129e965e010000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd0401408ee2187395071a089e3b9743b1a718fa28a8700676451317f7454aade98cf779b0afb5634a7e104f92e2df8e8b1c1b7b3b0e9fd61f4c0e9ea07ce112cef12b9a40fcb441c89b0c2047ba71a86d759bc2554dda55369798e6ab63e6c7713b06a8178f13586edf6a673f20bf5ed7bdc727f9e0c6f487cf667e505a26236d73887ae940691972a6f4ccef19a03a3d5948dfcf992af2c6a3c5b033a0f9235d2b8967291d9f61495ff1a681f240517c8d892eaa805e667bca40abcf03d441c68a9ec59deb4005890a59d83c7cb0416895e4768123e900603d5b140bf799bc9879fb628c598193db2b7a8e07ab54733c1c67b60c97a1a8048961cc0afd0b048e878866ffd7298b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae00"
return &expected
},
},
{
name: "positive, verbose 0",
params: `["7c32645dab0d87cfaddd5db053e2430c669f807e9efc2b91d1f50a824893352f", 0]`,
params: `["02b9e6f634578f34c6026f1676e25aa04f58889a320fba8bc632c6fe48c26cf1", 0]`,
result: func(e *executor) interface{} {
expected := "000000002534685cc322d339f957ea368a654bf30b834be4cac0b8441375cce2a37630625507db78d2a2f3130c6073bd68f57202248fdc8966fa8706e88eb0fc61df74085384945e010000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd040140b622b3bdddb8c5e52ae8b4bce5665eb6e2aca950ba72386ea0d37e364af2c7fc40f009c47e1a2140bee90d1e2f81c705d6f2499fe6230b27d1f225c45f38d3c440ec01e743024c2c63dccb2ca4a555eeadb2e6115fe6bc42a8d5c17093828e4ea779b36c6d1535c70c047c709183fc1c93139153291dd0edb614dd3e17d67038dd400f7635816214254b7fba0bb480e2a0ab149c84854adcb542124e67f4cedbf551690f8048271c3f05bbe50f576dcbaf3607afffa2551480cdc24908df0fd47c60408d724d6cfb9bf99e38dc42974f084d110057d3f23a04f5bbf99f5712dad17ae842416bb3e30fee034a317280565cb772f8a61fd09cb05e76db27c5fc7722819f8b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae00"
expected := "000000009456b8c7f89bdfe012a30a2be9af5218e048ae7372115ce3e39cc847c01e9e7f9cffa26c112eb147a995520e47afbc45a192d9bf1a8e9b8f80497e5d92c4e9f2129e965e010000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd0401408ee2187395071a089e3b9743b1a718fa28a8700676451317f7454aade98cf779b0afb5634a7e104f92e2df8e8b1c1b7b3b0e9fd61f4c0e9ea07ce112cef12b9a40fcb441c89b0c2047ba71a86d759bc2554dda55369798e6ab63e6c7713b06a8178f13586edf6a673f20bf5ed7bdc727f9e0c6f487cf667e505a26236d73887ae940691972a6f4ccef19a03a3d5948dfcf992af2c6a3c5b033a0f9235d2b8967291d9f61495ff1a681f240517c8d892eaa805e667bca40abcf03d441c68a9ec59deb4005890a59d83c7cb0416895e4768123e900603d5b140bf799bc9879fb628c598193db2b7a8e07ab54733c1c67b60c97a1a8048961cc0afd0b048e878866ffd7298b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae00"
return &expected
},
},
{
name: "positive, verbose !=0",
params: `["7c32645dab0d87cfaddd5db053e2430c669f807e9efc2b91d1f50a824893352f", 2]`,
params: `["02b9e6f634578f34c6026f1676e25aa04f58889a320fba8bc632c6fe48c26cf1", 2]`,
result: func(e *executor) interface{} {
hash, err := util.Uint256DecodeStringLE("7c32645dab0d87cfaddd5db053e2430c669f807e9efc2b91d1f50a824893352f")
hash, err := util.Uint256DecodeStringLE("02b9e6f634578f34c6026f1676e25aa04f58889a320fba8bc632c6fe48c26cf1")
if err != nil {
panic("can not decode hash parameter")
}
@ -520,7 +520,7 @@ var rpcTestCases = map[string][]rpcTestCase{
params: `["AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU"]`,
result: func(*executor) interface{} {
// hash of the issueTx
h, _ := util.Uint256DecodeStringBE("6a46738cd6f821d3b2d96e68c3feb5fcfe81d08a711baadbb68cbfb034fa29c5")
h, _ := util.Uint256DecodeStringBE("7b5710faf4ea62e3cd7f526d3dad39e85e1823c62340c88b80e36fd99342457a")
amount := util.Fixed8FromInt64(1 * 8) // (endHeight - startHeight) * genAmount[0]
return &result.ClaimableInfo{
Spents: []result.Claimable{
@ -579,7 +579,7 @@ var rpcTestCases = map[string][]rpcTestCase{
"gettransactionheight": {
{
name: "poositive",
params: `["3fe72668fa667b8bb0a77ac2375402d52fafc18e6d0a4c12a401dc69bdf515c2"]`,
params: `["2f0ed00979cb5feae842946be2afb96deec9c13236605fda63737db223089a00"]`,
result: func(e *executor) interface{} {
h := 1
return &h
@ -791,7 +791,7 @@ var rpcTestCases = map[string][]rpcTestCase{
"sendrawtransaction": {
{
name: "positive",
params: `["80001300000000015b090ad71ea0c192adc820401b2edc6a197788ee8e5e42a9c5e5e00d700c5da1010001250815d6e93c89e6d2f7279bd5781317d1bfb1ee30aca4c338524654563b3acd0030d3dec38623002baa76ad534b886cb87c6b3720a34943d9000fa90141409646e3dd0dd87685eadac1f682fa63db83729f780a7b2e739cb372ceeaadb3f19260060b34c83fec46e48a6288b2bc5c641e75d1cb358e9c185425a2e6e3fdab232102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2ac"]`,
params: `["800013000000b004000000010655773cea2a4f8cc66f83989605a58e87e885b6aaf58d450db3b83f81a2c950010001a9bf999e43ccfe9d40c3450fc75ca4b02db9b1691a7e1989b331f621456289050030d3dec38623002baa76ad534b886cb87c6b3720a34943d9000fa9014140faa7f2c3f700838aa48be950aff762c050f1cf04f1185fb3893820f63a98ccbfed05e8c5931f67ade59054c853be1d37ff9e75ed65b0543255ff28a3f8667670232102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2ac"]`,
result: func(e *executor) interface{} {
v := true
return &v
@ -822,7 +822,7 @@ var rpcTestCases = map[string][]rpcTestCase{
{
// If you are planning to modify test chain from `testblocks.acc`, please, update param value (first block)
name: "empty block",
params: `["00000000565f6b8fab486930d5ece5feb93060f010b556b2d4aa618878326ed93604ed6400000000000000000000000000000000000000000000000000000000000000002385945ed10000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd0401408313b36a61c137d327bec8791dfbb22ae9627fbcd2b023236f65188376f1ff4913c554b276cf7e84c5446fb495df2ed7cd34577ef9a4f9dd0dd27654aa53abe040acf3d5327c50e08bf97d794b6ec021223b8c493f9b71f8844446a01a99e555d517d30b84cbb2a5dcbafb5171373f4d0e6c8aea54f46901455d62545f75bdd2a640c359e2365bfe6f9b7b58a09e7e78f2bee85dbb4f823f9bee31b297cb2eb804eb4a5f1858a729d9676ab2c63b91bee5726c7b38086a04f3fe0ca23155331c476840dfddf4c173a374aacff6d2f37b327256556aa37d7c38c41dfda1f42d25f33d921b41da271aa27f7872f7b2b0b00f90a7ee83f5823ea1cc4f9db90a0100a8b7868b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae00"]`,
params: `["0000000029e2ea0ec5c9aa98fa736b52750916b3b8ab5cdbe7647fb6d0b7f6dac35865640000000000000000000000000000000000000000000000000000000000000000e29e965ed10000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd040140efdc94ac1e5c7588a1e70aa2ada3450631f30b15676861e7f32159f0e0b97e5fec8dd9870d92755e76b2cf3d6a90f06c2f6a7b782248ac4b765433beb6891a4840551f59a1e88395290ea2273500c60fc55b0d33ab6c3ddd565177f77083e82aaffca3553a0a116b457d5101f8627da39a3a24f19e2d04fab7e65670fda6a50f4140576969f478e6150b128b1149dd3c8b663f27bda53a6815fe177d52abc6ad40311a4fcba14a0d9286d6cda521cd9bc0ade09a66e88059da84363512c6110f4dc94008e8c0e6f3835281690fa0d594a6f5f1914b2f047fe835b134641b5a19935a4f6b10931ad168e47f96f6bf98380c0f060d4b25ae71869c4ef9d2a92a262eceeb8b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae00"]`,
fail: true,
},
{
@ -848,7 +848,7 @@ var rpcTestCases = map[string][]rpcTestCase{
{
name: "positive",
// If you are planning to modify test chain from `testblocks.acc`, please, update param value (second block)
params: `["00000000565f6b8fab486930d5ece5feb93060f010b556b2d4aa618878326ed93604ed645c23aae5b26be3d759680239a4276be0d2e76de303ef3fda96da97e8a3f6a0f12385945ed10000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd040140accd1571b3c25e4a6ec80f3bfc8ca3360f51232ed615b756e88424c1c083bd4c0d37f98156c8b87a36710467a75ff3938acea5bbd6a683d439004e2a30665562405de64537c7a411055504bec46851101a3ee9a3db02a7fb0feff781bee43a71ff7e76e03f273437bb94ad1f58dbe29eff32d9299bae0f48860a89a74ed5a48900400a337ce23f8dd767d043ba2b0886ba25d3905a1493ba70a96b297179914d096dfb8621f40e5efa63205af46b8ae71198846affcf02b9137752fcf3d54a683faa408d54fcd4d5235ff48b8dbe7d6f2e0b75ea3dc1bcd563ae44c8c8df201f5039fd30357d8c6709a0639a4aef07a223ca2ae21a74494808bc8b8f2955e7b26bdd148b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae0100001400000000000000"]`,
params: `["0000000029e2ea0ec5c9aa98fa736b52750916b3b8ab5cdbe7647fb6d0b7f6dac3586564980135e10c52e5444c962659b388a5b226114a45d3912a88700ac6b05aaaf961e29e965ed10000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd040140a0ed19af416fc4edb6e32b4687290d4eff1262af338dc8e55021a13f500ce94377c0fca593db15e29a0ee11b229d8bb48bd75203834829aee47096ff375ef8e240bcccad08d1ae7cc47c099eb4321a1fe07cf77a434841fd48a04aaf19204ec5bbf465533a2845a323710ea068316f50be82c384c82e0a5a509b2a9442c6a7909640de0a52dd615efac136971be900700ec39a84198e7d1639e880955022901a8d98ff39f00e858b41686047d68d7c18963b9def50a85907eb3b0bfbba7b2fa64d814060670b0c648757594cdba09aafc158ee6f7e88fbd2aa088a8c57bff2c8e7ddd83fa242632e1b6f82e3af2b3d0428c3936833cefb7ced1cc3c50ec29da906eb498b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae01000014000000b004000000000000"]`,
result: func(e *executor) interface{} {
v := true
return &v
@ -921,7 +921,7 @@ func TestRPC(t *testing.T) {
var res string
err := json.Unmarshal(result, &res)
require.NoErrorf(t, err, "could not parse response: %s", result)
assert.Equal(t, "40000000000000455b7b226c616e67223a227a682d434e222c226e616d65223a22e5b08fe89a81e882a1227d2c7b226c616e67223a22656e222c226e616d65223a22416e745368617265227d5d0000c16ff28623000000da1745e9b549bd0bfa1a569971c77eba30cd5a4b00000000", res)
assert.Equal(t, "4000000000000000000000455b7b226c616e67223a227a682d434e222c226e616d65223a22e5b08fe89a81e882a1227d2c7b226c616e67223a22656e222c226e616d65223a22416e745368617265227d5d0000c16ff28623000000da1745e9b549bd0bfa1a569971c77eba30cd5a4b00000000", res)
})
t.Run("getrawtransaction 2 arguments", func(t *testing.T) {
@ -933,7 +933,7 @@ func TestRPC(t *testing.T) {
var res string
err := json.Unmarshal(result, &res)
require.NoErrorf(t, err, "could not parse response: %s", result)
assert.Equal(t, "40000000000000455b7b226c616e67223a227a682d434e222c226e616d65223a22e5b08fe89a81e882a1227d2c7b226c616e67223a22656e222c226e616d65223a22416e745368617265227d5d0000c16ff28623000000da1745e9b549bd0bfa1a569971c77eba30cd5a4b00000000", res)
assert.Equal(t, "4000000000000000000000455b7b226c616e67223a227a682d434e222c226e616d65223a22e5b08fe89a81e882a1227d2c7b226c616e67223a22656e222c226e616d65223a22416e745368617265227d5d0000c16ff28623000000da1745e9b549bd0bfa1a569971c77eba30cd5a4b00000000", res)
})
t.Run("getrawtransaction 2 arguments, verbose", func(t *testing.T) {
@ -973,7 +973,7 @@ func TestRPC(t *testing.T) {
err := json.Unmarshal(res, &txOut)
require.NoErrorf(t, err, "could not parse response: %s", res)
assert.Equal(t, 0, txOut.N)
assert.Equal(t, "0x250815d6e93c89e6d2f7279bd5781317d1bfb1ee30aca4c338524654563b3acd", txOut.Asset)
assert.Equal(t, "0xa9bf999e43ccfe9d40c3450fc75ca4b02db9b1691a7e1989b331f62145628905", txOut.Asset)
assert.Equal(t, util.Fixed8FromInt64(100000000), txOut.Value)
assert.Equal(t, "AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU", txOut.Address)
})

Binary file not shown.