changed implementation of debug_update
Fixes and changes related to #254 based on !1025 (closed) by @asuch
The best illustration of how debug_update
works now is in new unit test debug_node/debug_update_transaction_order
.
There are two modes - with internal transaction (covers previous use cases) and new with explicit user transaction.
New mode with explicit user transaction works the following way: debug_update
, aside from lambda to be executed, is given transaction id of not-yet-pushed user transaction. Lambda is registered as callback hooked to that transaction id. When user transaction is finally pushed (which does not need to be immediately for nearest block) and later reapplied as pending, during block generation and block application, each of those times registered callback is executed right before transaction. It was made specifically for debug_set_vest_price
in mind - to be hooked with explicit transfer_to_vesting_operation
, so the "price fixing" and "price stabilization" are guaranteed to be part of single block (otherwise once in a while there might be gap between both steps, which means inflation is changing price for second step destabilizing tests). It can be used in similar cases when direct modifications of state are needed as preparation for specific transaction.
Mode with internal transaction is used when call does not contain transaction id. When that happens, transaction is generated internally (empty custom_operation
with use of temp
s open authority, which means no need for signature) and immediately pushed to become pending. Given lambda is then executed and hooked to internal transaction to be repeated on transaction reapplication. The same internal transaction is reused for consecutive calls to debug_update
, until the sequence is broken by some user transaction or generation of block. To make sure internal transaction is properly reapplied, special checks are in place that cause hard exception at the end of block application in case there was some problem preventing transaction from execution (example of such problem was already in unit tests: change of timestamp of head block caused internal transaction to become expired when block was generated).
Caller of new debug_update
needs to take heed of one more thing: since there is witness plugin limit on number of custom operations per user per block (default 5), if there are too many debug_update
calls separated with regular transactions, all targeted for the same block, the mechanism will prevent execution of debug_update
that would break that limit. The limit can be changed in testnet configuration, it can also be avoided if debug_update
calls are hooked to transactions separating them instead of relying on internal transactions.
Fixes:
-
#254 - added unit test for new mode with explicit hooks and for mixing
debug_update
calls with regular transactions - bug with
debug_set_vest_price
(access to reference to local variable inside lambda - does not work when that variable was already killed) - added unit test to show the bug
Changes in unit tests:
- eliminated some uses of
debug_update
that no longer work (like changing of head block time too much that cause internal transactions to be expired when next block is generated) - fixed values in tests that check exact RC cost (internal transactions use RC pools therefore influence the cost)
- added workaround for tests that used too many
debug_update
calls separated by regular transactions
debug_node_api
changes:
-
debug_generate_blocks
/debug_generate_blocks_until
no longer change witness key (whenedit_if_needed
is set) in case the witness that needs to generate block has different key than given asdebug_key
); instead the block is now generated with no witness signature (and applied withskip_witness_signature
flag) -
debug_set_hardfork
anddebug_set_vest_price
have new optional argumenthook_to_tx
where caller can pass id of transaction, so setting hardfork / setting vest price is executed right before that transaction