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

@ -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
}