Issue #157 - make trx expiration absolute
This is done to comply with the policy that transactions should be self describing and not depend upon implied state. This makes things easier for everyone to understand exactly when a transaction will be invalid without having to refer to chain state.
This commit is contained in:
parent
da254cdbff
commit
cfa95a3f57
12 changed files with 65 additions and 144 deletions
|
|
@ -471,8 +471,7 @@ processed_transaction database::_apply_transaction(const signed_transaction& trx
|
|||
const chain_parameters& chain_parameters = get_global_properties().parameters;
|
||||
eval_state._trx = &trx;
|
||||
|
||||
//This check is used only if this transaction has an absolute expiration time.
|
||||
if( !(skip & skip_transaction_signatures) && trx.relative_expiration == 0 )
|
||||
if( !(skip & skip_transaction_signatures) )
|
||||
{
|
||||
eval_state._sigs.reserve(trx.signatures.size());
|
||||
|
||||
|
|
@ -484,105 +483,27 @@ processed_transaction database::_apply_transaction(const signed_transaction& trx
|
|||
}
|
||||
}
|
||||
|
||||
//If we're skipping tapos check, but not dupe check, assume all transactions have maximum expiration time.
|
||||
fc::time_point_sec trx_expiration = _pending_block.timestamp + chain_parameters.maximum_time_until_expiration;
|
||||
|
||||
//Skip all manner of expiration and TaPoS checking if we're on block 1; It's impossible that the transaction is
|
||||
//expired, and TaPoS makes no sense as no blocks exist.
|
||||
if( BOOST_LIKELY(head_block_num() > 0) )
|
||||
{
|
||||
if( !(skip & skip_tapos_check) && trx.relative_expiration != 0 )
|
||||
if( !(skip & skip_tapos_check) )
|
||||
{
|
||||
//Check the TaPoS reference and expiration time
|
||||
//Remember that the TaPoS block number is abbreviated; it contains only the lower 16 bits.
|
||||
//Lookup TaPoS block summary by block number (remember block summary instances are the block numbers)
|
||||
|
||||
// Let N = head_block_num(), a = N & 0xFFFF, and r = trx.ref_block_num
|
||||
//
|
||||
// We want to solve for the largest block height x such that
|
||||
// these two conditions hold:
|
||||
//
|
||||
// (a) 0x10000 divides x-r
|
||||
// (b) x <= N
|
||||
//
|
||||
// Let us define:
|
||||
//
|
||||
// x1 = N-a+r
|
||||
// x0 = x1-2^16
|
||||
// x2 = x1+2^16
|
||||
//
|
||||
// It is clear that x0, x1, x2 are consecutive solutions to (a).
|
||||
//
|
||||
// Since r < 2^16 and a < 2^16, it follows that
|
||||
// -2^16 < r-a < 2^16. From this we know that x0 < N and x2 > N.
|
||||
//
|
||||
// Case (1): x1 <= N. In this case, x1 must be the greatest
|
||||
// integer that satisfies (a) and (b); for x2, the next
|
||||
// largest integer that satisfies (a), does not satisfy (b).
|
||||
//
|
||||
// Case (2): x1 > N. In this case, x0 must be the greatest
|
||||
// integer that satisfies (a) and (b); for x1, the next
|
||||
// largest integer that satisfies (a), does not satisfy (b).
|
||||
//
|
||||
/**
|
||||
int64_t N = head_block_num();
|
||||
int64_t a = N & 0xFFFF;
|
||||
int64_t r = trx.ref_block_num;
|
||||
|
||||
int64_t x1 = N-a+r;
|
||||
int64_t x0 = x1 - 0x10000;
|
||||
int64_t x2 = x1 + 0x10000;
|
||||
|
||||
assert( x0 < N );
|
||||
assert( x1 >= 0 );
|
||||
assert( x2 > N );
|
||||
|
||||
uint32_t ref_block_height;
|
||||
if( x1 <= N )
|
||||
{
|
||||
FC_ASSERT( x1 > 0 );
|
||||
ref_block_height = uint32_t( x1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
ref_block_height = uint32_t( x0 );
|
||||
}
|
||||
*/
|
||||
|
||||
const auto& tapos_block_summary = block_summary_id_type( trx.ref_block_num )(*this);
|
||||
|
||||
//This is the signature check for transactions with relative expiration.
|
||||
if( !(skip & skip_transaction_signatures) )
|
||||
{
|
||||
eval_state._sigs.reserve(trx.signatures.size());
|
||||
|
||||
for( const auto& sig : trx.signatures )
|
||||
{
|
||||
FC_ASSERT(eval_state._sigs.insert(std::make_pair(
|
||||
public_key_type( fc::ecc::public_key(sig, trx.digest())),
|
||||
false)).second,
|
||||
"Multiple signatures by same key detected");
|
||||
}
|
||||
}
|
||||
|
||||
//Verify TaPoS block summary has correct ID prefix, and that this block's time is not past the expiration
|
||||
FC_ASSERT( trx.ref_block_prefix == tapos_block_summary.block_id._hash[1] );
|
||||
trx_expiration = tapos_block_summary.timestamp + chain_parameters.block_interval*trx.relative_expiration;
|
||||
} else if( trx.relative_expiration == 0 ) {
|
||||
trx_expiration = fc::time_point_sec() + fc::seconds(trx.ref_block_prefix);
|
||||
FC_ASSERT( trx_expiration <= _pending_block.timestamp + chain_parameters.maximum_time_until_expiration, "",
|
||||
("trx_expiration",trx_expiration)("_pending_block.timestamp",_pending_block.timestamp)("max_til_exp",chain_parameters.maximum_time_until_expiration));
|
||||
}
|
||||
FC_ASSERT( _pending_block.timestamp <= trx_expiration, "", ("pending.timestamp",_pending_block.timestamp)("trx_exp",trx_expiration) );
|
||||
} else if( !(skip & skip_transaction_signatures) ) {
|
||||
FC_ASSERT(trx.relative_expiration == 0, "May not use transactions with a reference block in block 1!");
|
||||
}
|
||||
}
|
||||
|
||||
FC_ASSERT( trx.expiration <= _pending_block.timestamp + chain_parameters.maximum_time_until_expiration, "",
|
||||
("trx.expiration",trx.expiration)("_pending_block.timestamp",_pending_block.timestamp)("max_til_exp",chain_parameters.maximum_time_until_expiration));
|
||||
FC_ASSERT( _pending_block.timestamp <= trx.expiration, "", ("pending.timestamp",_pending_block.timestamp)("trx.exp",trx.expiration) );
|
||||
}
|
||||
|
||||
//Insert transaction into unique transactions database.
|
||||
if( !(skip & skip_transaction_dupe_check) )
|
||||
{
|
||||
create<transaction_object>([&](transaction_object& transaction) {
|
||||
transaction.expiration = trx_expiration;
|
||||
transaction.trx_id = trx_id;
|
||||
transaction.trx = trx;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ void database::clear_expired_transactions()
|
|||
const auto& global_parameters = get_global_properties().parameters;
|
||||
auto forking_window_time = global_parameters.maximum_undo_history * global_parameters.block_interval;
|
||||
while( !dedupe_index.empty()
|
||||
&& head_block_time() - dedupe_index.rbegin()->expiration >= fc::seconds(forking_window_time) )
|
||||
&& head_block_time() - dedupe_index.rbegin()->trx.expiration >= fc::seconds(forking_window_time) )
|
||||
transaction_idx.remove(*dedupe_index.rbegin());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,20 +34,8 @@ namespace graphene { namespace chain {
|
|||
* hours with a 1 second interval.
|
||||
*
|
||||
* All transactions must expire so that the network does not have to maintain a permanent record of all transactions
|
||||
* ever published. There are two accepted ways to specify the transaction's expiration time. The first is to choose
|
||||
* a reference block, which is generally the most recent block the wallet is aware of when it signs the transaction,
|
||||
* and specify a number of block intervals after the reference block until the transaction expires. The second
|
||||
* expiration mechanism is to explicitly specify a timestamp of expiration.
|
||||
*
|
||||
* Note: The number of block intervals is different than the number of blocks. In effect the maximum period that a
|
||||
* transaction is theoretically valid is 18 hours (1 sec interval) to 3.5 days (5 sec interval) if the reference
|
||||
* block was the most recent block.
|
||||
*
|
||||
* If a transaction is to expire after a number of block intervals from a reference block, the reference block
|
||||
* should be identified in the transaction header using the @ref ref_block_num, @ref ref_block_prefix, and @ref
|
||||
* relative_expiration fields. If the transaction is instead to expire at an absolute timestamp, @ref
|
||||
* ref_block_prefix should be treated as a 32-bit timestamp of the expiration time, and @ref ref_block_num and @ref
|
||||
* relative_expiration must both be set to zero.
|
||||
* ever published. A transaction may not have an expiration date too far in the future because this would require
|
||||
* keeping too much transaction history in memory.
|
||||
*
|
||||
* The block prefix is the first 4 bytes of the block hash of the reference block number, which is the second 4
|
||||
* bytes of the @ref block_id_type (the first 4 bytes of the block ID are the block number)
|
||||
|
|
@ -58,7 +46,7 @@ namespace graphene { namespace chain {
|
|||
* probably have a longer re-org window to ensure their transaction can still go through in the event of a momentary
|
||||
* disruption in service.
|
||||
*
|
||||
* @note It is not recommended to set the @ref ref_block_num, @ref ref_block_prefix, and @ref relative_expiration
|
||||
* @note It is not recommended to set the @ref ref_block_num, @ref ref_block_prefix, and @ref expiration
|
||||
* fields manually. Call the appropriate overload of @ref set_expiration instead.
|
||||
*
|
||||
* @{
|
||||
|
|
@ -80,12 +68,12 @@ namespace graphene { namespace chain {
|
|||
* @ref block_id_type
|
||||
*/
|
||||
uint32_t ref_block_prefix = 0;
|
||||
|
||||
/**
|
||||
* This field specifies the number of block intervals after the reference block until this transaction becomes
|
||||
* invalid. If this field is set to zero, the @ref ref_block_prefix is interpreted as an absolute timestamp of
|
||||
* the time the transaction becomes invalid.
|
||||
* This field specifies the absolute expiration for this transaction.
|
||||
*/
|
||||
uint16_t relative_expiration = 1;
|
||||
fc::time_point_sec expiration;
|
||||
|
||||
vector<operation> operations;
|
||||
extensions_type extensions;
|
||||
|
||||
|
|
@ -95,7 +83,7 @@ namespace graphene { namespace chain {
|
|||
void validate() const;
|
||||
|
||||
void set_expiration( fc::time_point_sec expiration_time );
|
||||
void set_expiration( const block_id_type& reference_block, unsigned_int lifetime_intervals = 3 );
|
||||
void set_reference_block( const block_id_type& reference_block );
|
||||
|
||||
/// visit all operations
|
||||
template<typename Visitor>
|
||||
|
|
@ -182,6 +170,6 @@ namespace graphene { namespace chain {
|
|||
|
||||
} }
|
||||
|
||||
FC_REFLECT( graphene::chain::transaction, (ref_block_num)(ref_block_prefix)(relative_expiration)(operations)(extensions) )
|
||||
FC_REFLECT( graphene::chain::transaction, (ref_block_num)(ref_block_prefix)(expiration)(operations)(extensions) )
|
||||
FC_REFLECT_DERIVED( graphene::chain::signed_transaction, (graphene::chain::transaction), (signatures) )
|
||||
FC_REFLECT_DERIVED( graphene::chain::processed_transaction, (graphene::chain::signed_transaction), (operation_results) )
|
||||
|
|
|
|||
|
|
@ -45,8 +45,9 @@ namespace graphene { namespace chain {
|
|||
static const uint8_t type_id = impl_transaction_object_type;
|
||||
|
||||
signed_transaction trx;
|
||||
time_point_sec expiration;
|
||||
transaction_id_type trx_id;
|
||||
|
||||
time_point_sec get_expiration()const { return trx.expiration; }
|
||||
};
|
||||
|
||||
struct by_expiration;
|
||||
|
|
@ -57,11 +58,11 @@ namespace graphene { namespace chain {
|
|||
indexed_by<
|
||||
hashed_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
|
||||
hashed_unique< tag<by_trx_id>, BOOST_MULTI_INDEX_MEMBER(transaction_object, transaction_id_type, trx_id), std::hash<transaction_id_type> >,
|
||||
ordered_non_unique< tag<by_expiration>, BOOST_MULTI_INDEX_MEMBER(transaction_object, time_point_sec, expiration)>
|
||||
ordered_non_unique< tag<by_expiration>, const_mem_fun<transaction_object, time_point_sec, &transaction_object::get_expiration > >
|
||||
>
|
||||
> transaction_multi_index_type;
|
||||
|
||||
typedef generic_index<transaction_object, transaction_multi_index_type> transaction_index;
|
||||
} }
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::transaction_object, (graphene::db::object), (trx)(expiration) )
|
||||
FC_REFLECT_DERIVED( graphene::chain::transaction_object, (graphene::db::object), (trx)(trx_id) )
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ object_id_type proposal_create_evaluator::do_apply(const proposal_create_operati
|
|||
database& d = db();
|
||||
|
||||
const proposal_object& proposal = d.create<proposal_object>([&](proposal_object& proposal) {
|
||||
_proposed_trx.expiration = o.expiration_time;
|
||||
proposal.proposed_transaction = _proposed_trx;
|
||||
proposal.expiration_time = o.expiration_time;
|
||||
if( o.review_period_seconds )
|
||||
|
|
|
|||
|
|
@ -37,9 +37,6 @@ digest_type transaction::digest()const
|
|||
}
|
||||
void transaction::validate() const
|
||||
{
|
||||
if( relative_expiration == 0 )
|
||||
FC_ASSERT( ref_block_num == 0 && ref_block_prefix > 0 );
|
||||
|
||||
for( const auto& op : operations )
|
||||
operation_validate(op);
|
||||
}
|
||||
|
|
@ -66,16 +63,14 @@ signature_type graphene::chain::signed_transaction::sign(const private_key_type&
|
|||
|
||||
void transaction::set_expiration( fc::time_point_sec expiration_time )
|
||||
{
|
||||
ref_block_num = 0;
|
||||
relative_expiration = 0;
|
||||
ref_block_prefix = expiration_time.sec_since_epoch();
|
||||
expiration = expiration_time;
|
||||
}
|
||||
|
||||
void transaction::set_expiration( const block_id_type& reference_block, unsigned_int lifetime_intervals )
|
||||
void transaction::set_reference_block( const block_id_type& reference_block )
|
||||
{
|
||||
ref_block_num = fc::endian_reverse_u32(reference_block._hash[0]);
|
||||
if( ref_block_num == 0 ) ref_block_prefix = 0;
|
||||
ref_block_prefix = reference_block._hash[1];
|
||||
relative_expiration = lifetime_intervals;
|
||||
}
|
||||
|
||||
void transaction::get_required_authorities( flat_set<account_id_type>& active, flat_set<account_id_type>& owner, vector<authority>& other )const
|
||||
|
|
|
|||
|
|
@ -727,7 +727,9 @@ public:
|
|||
|
||||
vector<public_key_type> paying_keys = registrar_account_object.active.get_keys();
|
||||
|
||||
tx.set_expiration(get_dynamic_global_properties().head_block_id);
|
||||
auto dyn_props = get_dynamic_global_properties();
|
||||
tx.set_reference_block( dyn_props.head_block_id );
|
||||
tx.set_expiration( dyn_props.time + fc::seconds(30) );
|
||||
tx.validate();
|
||||
|
||||
for( public_key_type& key : paying_keys )
|
||||
|
|
@ -851,7 +853,9 @@ public:
|
|||
|
||||
vector<public_key_type> paying_keys = registrar_account_object.active.get_keys();
|
||||
|
||||
tx.set_expiration(get_dynamic_global_properties().head_block_id);
|
||||
auto dyn_props = get_dynamic_global_properties();
|
||||
tx.set_reference_block( dyn_props.head_block_id );
|
||||
tx.set_expiration( dyn_props.time + fc::seconds(30) );
|
||||
tx.validate();
|
||||
|
||||
for( public_key_type& key : paying_keys )
|
||||
|
|
@ -1434,7 +1438,9 @@ public:
|
|||
approving_key_set.insert( k.first );
|
||||
}
|
||||
|
||||
tx.set_expiration(get_dynamic_global_properties().head_block_id);
|
||||
auto dyn_props = get_dynamic_global_properties();
|
||||
tx.set_reference_block( dyn_props.head_block_id );
|
||||
tx.set_expiration( dyn_props.time + fc::seconds(30) );
|
||||
|
||||
for( public_key_type& key : approving_key_set )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -424,13 +424,16 @@ BOOST_FIXTURE_TEST_CASE( tapos_rollover, database_fixture )
|
|||
xfer_op.amount = asset(1000);
|
||||
|
||||
xfer_tx.operations.push_back( xfer_op );
|
||||
xfer_tx.set_expiration( db.head_block_id(), 0x1000 );
|
||||
xfer_tx.set_expiration( db.head_block_time() + fc::seconds( 0x1000 * db.get_global_properties().parameters.block_interval ) );
|
||||
xfer_tx.set_reference_block( db.head_block_id() );
|
||||
|
||||
sign( xfer_tx, alice_private_key );
|
||||
PUSH_TX( db, xfer_tx, 0 );
|
||||
generate_block();
|
||||
|
||||
BOOST_TEST_MESSAGE( "Sign new tx's" );
|
||||
xfer_tx.set_expiration( db.head_block_id(), 0x1000 );
|
||||
xfer_tx.set_expiration( db.head_block_time() + fc::seconds( 0x1000 * db.get_global_properties().parameters.block_interval ) );
|
||||
xfer_tx.set_reference_block( db.head_block_id() );
|
||||
xfer_tx.signatures.clear();
|
||||
sign( xfer_tx, alice_private_key );
|
||||
|
||||
|
|
|
|||
|
|
@ -337,7 +337,8 @@ BOOST_AUTO_TEST_CASE( proposed_single_account )
|
|||
}
|
||||
|
||||
trx.operations.push_back(op);
|
||||
trx.set_expiration(db.head_block_id());
|
||||
trx.set_expiration( db.head_block_time() + fc::seconds( 3 * db.get_global_properties().parameters.block_interval ));
|
||||
trx.set_reference_block( db.head_block_id() );
|
||||
|
||||
//idump((moneyman));
|
||||
trx.sign( init_account_priv_key );
|
||||
|
|
@ -849,7 +850,8 @@ BOOST_FIXTURE_TEST_CASE( proposal_owner_authority_complete, database_fixture )
|
|||
|
||||
std::swap(uop.key_approvals_to_add, uop.key_approvals_to_remove);
|
||||
// Survive trx dupe check
|
||||
trx.set_expiration(db.head_block_id(), 5);
|
||||
trx.set_expiration( db.head_block_time() + fc::seconds( 5 * db.get_global_properties().parameters.block_interval ));
|
||||
trx.set_reference_block( db.head_block_id() );
|
||||
trx.operations.push_back(uop);
|
||||
trx.sign(nathan_key);
|
||||
trx.sign(dan_key);
|
||||
|
|
|
|||
|
|
@ -288,6 +288,7 @@ BOOST_AUTO_TEST_CASE( undo_pending )
|
|||
{
|
||||
signed_transaction trx;
|
||||
trx.set_expiration(db.head_block_time() + fc::minutes(1));
|
||||
|
||||
trx.operations.push_back(t);
|
||||
PUSH_TX( db, trx, ~0 );
|
||||
|
||||
|
|
@ -465,7 +466,8 @@ BOOST_AUTO_TEST_CASE( tapos )
|
|||
|
||||
signed_transaction trx;
|
||||
//This transaction must be in the next block after its reference, or it is invalid.
|
||||
trx.set_expiration(db1.head_block_id(), 1);
|
||||
trx.set_expiration( db1.head_block_time() + fc::seconds( 1 * db1.get_global_properties().parameters.block_interval ));
|
||||
trx.set_reference_block( db1.head_block_id() );
|
||||
|
||||
account_id_type nathan_id = account_idx.get_next_id();
|
||||
account_create_operation cop;
|
||||
|
|
@ -486,7 +488,8 @@ BOOST_AUTO_TEST_CASE( tapos )
|
|||
trx.sign(init_account_priv_key);
|
||||
//relative_expiration is 1, but ref block is 2 blocks old, so this should fail.
|
||||
GRAPHENE_REQUIRE_THROW(PUSH_TX( db1, trx, database::skip_transaction_signatures | database::skip_authority_check ), fc::exception);
|
||||
trx.set_expiration(db1.head_block_id(), 2);
|
||||
trx.set_expiration( db1.head_block_time() + fc::seconds( 2 * db1.get_global_properties().parameters.block_interval ));
|
||||
trx.set_reference_block( db1.head_block_id() );
|
||||
trx.signatures.clear();
|
||||
trx.sign(init_account_priv_key);
|
||||
db1.push_transaction(trx, database::skip_transaction_signatures | database::skip_authority_check);
|
||||
|
|
|
|||
|
|
@ -1143,7 +1143,8 @@ BOOST_AUTO_TEST_CASE( witness_withdraw_pay_test )
|
|||
account_upgrade_operation uop;
|
||||
uop.account_to_upgrade = nathan->get_id();
|
||||
uop.upgrade_to_lifetime_member = true;
|
||||
trx.set_expiration(db.head_block_id());
|
||||
trx.set_expiration( db.head_block_time() + fc::seconds( 3 * db.get_global_properties().parameters.block_interval ));
|
||||
trx.set_reference_block( db.head_block_id() );
|
||||
trx.operations.push_back(uop);
|
||||
for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op);
|
||||
trx.validate();
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ BOOST_AUTO_TEST_CASE( withdraw_permission_test )
|
|||
// withdraw 1
|
||||
trx.operations = {op};
|
||||
// make it different from previous trx so it's non-duplicate
|
||||
trx.ref_block_prefix++;
|
||||
trx.expiration += fc::seconds(1);
|
||||
trx.sign(dan_private_key);
|
||||
PUSH_TX( db, trx );
|
||||
trx.clear();
|
||||
|
|
@ -226,9 +226,9 @@ BOOST_AUTO_TEST_CASE( withdraw_permission_nominal_case )
|
|||
op.withdraw_to_account = dan_id;
|
||||
op.amount_to_withdraw = asset(5);
|
||||
trx.operations.push_back(op);
|
||||
// ref_block_prefix is timestamp, so treat it as a rollable nonce
|
||||
// expiration is timestamp, so treat it as a rollable nonce
|
||||
// so tx's have different txid's
|
||||
trx.ref_block_prefix++;
|
||||
trx.expiration += fc::seconds(1);
|
||||
trx.sign(dan_private_key);
|
||||
PUSH_TX( db, trx );
|
||||
// tx's involving withdraw_permissions can't delete it even
|
||||
|
|
@ -297,7 +297,7 @@ BOOST_AUTO_TEST_CASE( withdraw_permission_delete )
|
|||
withdraw_permission_delete_operation op;
|
||||
op.authorized_account = get_account("dan").id;
|
||||
op.withdraw_from_account = get_account("nathan").id;
|
||||
trx.set_expiration(db.head_block_id());
|
||||
trx.set_reference_block(db.head_block_id()); trx.set_expiration( db.head_block_time() + fc::seconds( 3 * db.get_global_properties().parameters.block_interval ) );
|
||||
trx.operations.push_back(op);
|
||||
trx.sign(generate_private_key("nathan"));
|
||||
PUSH_TX( db, trx );
|
||||
|
|
@ -415,7 +415,7 @@ BOOST_AUTO_TEST_CASE( witness_create )
|
|||
// Give nathan some voting stake
|
||||
transfer(committee_account, nathan_id, asset(10000000));
|
||||
generate_block();
|
||||
trx.set_expiration(db.head_block_id());
|
||||
trx.set_reference_block(db.head_block_id()); trx.set_expiration( db.head_block_time() + fc::seconds( 3 * db.get_global_properties().parameters.block_interval ) );
|
||||
|
||||
{
|
||||
account_update_operation op;
|
||||
|
|
@ -627,7 +627,7 @@ BOOST_AUTO_TEST_CASE( worker_pay_test )
|
|||
op.vesting_balance = worker_id_type()(db).worker.get<vesting_balance_worker_type>().balance;
|
||||
op.amount = asset(500);
|
||||
op.owner = nathan_id;
|
||||
trx.set_expiration(db.head_block_id());
|
||||
trx.set_reference_block(db.head_block_id()); trx.set_expiration( db.head_block_time() + fc::seconds( 3 * db.get_global_properties().parameters.block_interval ) );
|
||||
trx.operations.push_back(op);
|
||||
trx.sign( nathan_private_key);
|
||||
PUSH_TX( db, trx );
|
||||
|
|
@ -657,11 +657,11 @@ BOOST_AUTO_TEST_CASE( worker_pay_test )
|
|||
op.vesting_balance = worker_id_type()(db).worker.get<vesting_balance_worker_type>().balance;
|
||||
op.amount = asset(500);
|
||||
op.owner = nathan_id;
|
||||
trx.set_expiration(db.head_block_id());
|
||||
trx.set_reference_block(db.head_block_id()); trx.set_expiration( db.head_block_time() + fc::seconds( 3 * db.get_global_properties().parameters.block_interval ) );
|
||||
trx.operations.push_back(op);
|
||||
REQUIRE_THROW_WITH_VALUE(op, amount, asset(500));
|
||||
generate_blocks(db.head_block_time() + fc::hours(12));
|
||||
trx.set_expiration(db.head_block_id());
|
||||
trx.set_reference_block(db.head_block_id()); trx.set_expiration( db.head_block_time() + fc::seconds( 3 * db.get_global_properties().parameters.block_interval ) );
|
||||
REQUIRE_THROW_WITH_VALUE(op, amount, asset(501));
|
||||
trx.operations.back() = op;
|
||||
trx.sign( nathan_private_key);
|
||||
|
|
@ -680,7 +680,7 @@ BOOST_AUTO_TEST_CASE( refund_worker_test )
|
|||
upgrade_to_lifetime_member(nathan_id);
|
||||
generate_block();
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
trx.set_expiration(db.head_block_id());
|
||||
trx.set_reference_block(db.head_block_id()); trx.set_expiration( db.head_block_time() + fc::seconds( 3 * db.get_global_properties().parameters.block_interval ) );
|
||||
|
||||
{
|
||||
worker_create_operation op;
|
||||
|
|
@ -753,7 +753,7 @@ BOOST_AUTO_TEST_CASE( burn_worker_test )
|
|||
upgrade_to_lifetime_member(nathan_id);
|
||||
generate_block();
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
trx.set_expiration(db.head_block_id());
|
||||
trx.set_reference_block(db.head_block_id()); trx.set_expiration( db.head_block_time() + fc::seconds( 3 * db.get_global_properties().parameters.block_interval ) );
|
||||
|
||||
{
|
||||
worker_create_operation op;
|
||||
|
|
@ -933,7 +933,7 @@ BOOST_AUTO_TEST_CASE( unimp_force_settlement_unavailable )
|
|||
op.new_options = bit_usd(db).options;
|
||||
op.new_options.flags |= disable_force_settle;
|
||||
trx.operations.push_back(op);
|
||||
trx.set_expiration(db.head_block_id());
|
||||
trx.set_reference_block(db.head_block_id()); trx.set_expiration( db.head_block_time() + fc::seconds( 3 * db.get_global_properties().parameters.block_interval ) );
|
||||
trx.sign(key_id_type(), private_key);
|
||||
PUSH_TX( db, trx );
|
||||
//Check that force settlements were all canceled
|
||||
|
|
@ -1027,7 +1027,7 @@ BOOST_AUTO_TEST_CASE( balance_object_test )
|
|||
|
||||
auto slot = db.get_slot_at_time(starting_time);
|
||||
db.generate_block(starting_time, db.get_scheduled_witness(slot).first, init_account_priv_key, database::skip_nothing);
|
||||
trx.set_expiration(db.head_block_id());
|
||||
trx.set_reference_block(db.head_block_id()); trx.set_expiration( db.head_block_time() + fc::seconds( 3 * db.get_global_properties().parameters.block_interval ) );
|
||||
|
||||
const balance_object& vesting_balance_1 = balance_id_type(2)(db);
|
||||
const balance_object& vesting_balance_2 = balance_id_type(3)(db);
|
||||
|
|
@ -1080,7 +1080,7 @@ BOOST_AUTO_TEST_CASE( balance_object_test )
|
|||
db.generate_block(db.get_slot_time(1), db.get_scheduled_witness(1).first, init_account_priv_key, database::skip_nothing);
|
||||
slot = db.get_slot_at_time(vesting_balance_1.vesting_policy->begin_timestamp + 60);
|
||||
db.generate_block(db.get_slot_time(slot), db.get_scheduled_witness(slot).first, init_account_priv_key, database::skip_nothing);
|
||||
trx.set_expiration(db.head_block_id());
|
||||
trx.set_reference_block(db.head_block_id()); trx.set_expiration( db.head_block_time() + fc::seconds( 3 * db.get_global_properties().parameters.block_interval ) );
|
||||
|
||||
op.balance_to_claim = vesting_balance_1.id;
|
||||
op.total_claimed.amount = 500;
|
||||
|
|
@ -1106,7 +1106,7 @@ BOOST_AUTO_TEST_CASE( balance_object_test )
|
|||
db.generate_block(db.get_slot_time(1), db.get_scheduled_witness(1).first, init_account_priv_key, database::skip_nothing);
|
||||
slot = db.get_slot_at_time(db.head_block_time() + fc::days(1));
|
||||
db.generate_block(db.get_slot_time(slot), db.get_scheduled_witness(slot).first, init_account_priv_key, database::skip_nothing);
|
||||
trx.set_expiration(db.head_block_id());
|
||||
trx.set_reference_block(db.head_block_id()); trx.set_expiration( db.head_block_time() + fc::seconds( 3 * db.get_global_properties().parameters.block_interval ) );
|
||||
|
||||
op.total_claimed = vesting_balance_2.balance;
|
||||
trx.operations = {op};
|
||||
|
|
|
|||
Loading…
Reference in a new issue