Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTLC Changes #1998

Merged
merged 31 commits into from
Apr 28, 2020
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
895509a
Add memo to htlc
jmjatlanta Sep 20, 2019
04cccbc
Include HASH160 as available option
jmjatlanta Sep 20, 2019
dfbde9c
Add hardfork checks
jmjatlanta Sep 20, 2019
343c667
Bump DB_VERSION (BSIP64)
jmjatlanta Sep 20, 2019
2a5b29b
include preimage in operation history
jmjatlanta Apr 7, 2020
4264348
ref wallet - pretty-print htlc redeemed op
jmjatlanta Apr 7, 2020
a6bed6b
Update jmj_bsip_64 with hardfork changes
jmjatlanta Apr 11, 2020
a59540f
fixes for wallet operation_printer
jmjatlanta Apr 11, 2020
9975948
bsip64 memo fixes and addl testing
jmjatlanta Apr 15, 2020
7eee72c
fix constexpr warnings
jmjatlanta Apr 15, 2020
f161b38
verify hash appears in history
jmjatlanta Apr 15, 2020
f1a2ab0
add per kb fee for htlc memos
jmjatlanta Apr 15, 2020
0a55c64
bump FC for hash160 changes
jmjatlanta Apr 15, 2020
20e43f0
Adjust fee schedule
jmjatlanta Apr 18, 2020
5f68e64
do htlc hf checks in proposals
jmjatlanta Apr 18, 2020
bbab2f9
add preimage serialization
jmjatlanta Apr 18, 2020
b6bb193
adjust transfer_restricted logic
jmjatlanta Apr 18, 2020
1039366
Exclude memo on locked wallets
jmjatlanta Apr 18, 2020
3629d80
put print_memo in proper scope
jmjatlanta Apr 18, 2020
133f7c3
truncate long preimages in wallet output
jmjatlanta Apr 20, 2020
3e3df5a
standardize exact hardfork time
jmjatlanta Apr 20, 2020
ec78f4d
Use current (not default) memo fee
jmjatlanta Apr 20, 2020
fc15857
Detect overflow
jmjatlanta Apr 20, 2020
cf36230
remove decimal from test
jmjatlanta Apr 21, 2020
96112d4
BOOST_TEST_FAIL no longer part of Boost
jmjatlanta Apr 21, 2020
79a7abf
fee_helper refactor
jmjatlanta Apr 23, 2020
11f0b8c
Prevent exception if fee does not exist
jmjatlanta Apr 23, 2020
f2d76ad
merge changes from hardfork
jmjatlanta Apr 23, 2020
d02fd01
permit restricted transfers in proposals
jmjatlanta Apr 24, 2020
7cfcc52
merge of hf into feature branch
jmjatlanta Apr 24, 2020
e4472a9
Remove test spaghetti + minor fixes
jmjatlanta Apr 27, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions libraries/chain/hardfork.d/CORE_BSIP64.hf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// bitshares BSIP 64 HTLC modifications
#ifndef HARDFORK_CORE_BSIP64_TIME
#define HARDFORK_CORE_BSIP64_TIME (fc::time_point_sec( 1600000000 ) ) // Sep 2020
#endif
43 changes: 41 additions & 2 deletions libraries/chain/htlc_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,41 @@

namespace graphene {
namespace chain {
namespace detail
{
void check_htlc_create_hf_bsip64(const fc::time_point_sec& block_time,
const htlc_create_operation& op, const asset_object& asset_to_transfer)
{
if (block_time < HARDFORK_CORE_BSIP64_TIME)
{
// memo field added at harfork BSIP64
// NOTE: both of these checks can be removed after hardfork time
FC_ASSERT( !op.extensions.value.memo.valid(),
"Memo unavailable until after HARDFORK BSIP64");
// HASH160 added at hardfork BSIP64
FC_ASSERT( !op.preimage_hash.is_type<fc::hash160>(),
"HASH160 unavailable until after HARDFORK BSIP64" );
}
else
{
// this can be moved to the normal non-hf checks after HF_BSIP64
// IF there were no restricted transfers before HF_BSIP64
FC_ASSERT( !asset_to_transfer.is_transfer_restricted()
|| op.from == asset_to_transfer.issuer || op.to == asset_to_transfer.issuer,
"Asset ${asset} cannot be transfered.", ("asset", asset_to_transfer.id) );
}
}

void check_htlc_redeem_hf_bsip64(const fc::time_point_sec& block_time,
const htlc_redeem_operation& op, const htlc_object* htlc_obj)
{
// TODO: The hardfork portion of this check can be removed if no HTLC redemptions are
// attempted on an HTLC with a 0 preimage size before the hardfork date.
if ( htlc_obj->conditions.hash_lock.preimage_size > 0U ||
block_time < HARDFORK_CORE_BSIP64_TIME )
FC_ASSERT(op.preimage.size() == htlc_obj->conditions.hash_lock.preimage_size, "Preimage size mismatch.");
}
} // end of graphene::chain::details

optional<htlc_options> get_committee_htlc_options(graphene::chain::database& db)
{
Expand All @@ -51,6 +86,7 @@ namespace graphene {
const auto& asset_to_transfer = o.amount.asset_id( d );
const auto& from_account = o.from( d );
const auto& to_account = o.to( d );
detail::check_htlc_create_hf_bsip64(d.head_block_time(), o, asset_to_transfer);
FC_ASSERT( is_authorized_asset( d, from_account, asset_to_transfer ),
"Asset ${asset} is not authorized for account ${acct}.",
( "asset", asset_to_transfer.id )( "acct", from_account.id ) );
Expand All @@ -73,6 +109,8 @@ namespace graphene {
esc.transfer.asset_id = o.amount.asset_id;
esc.conditions.hash_lock.preimage_hash = o.preimage_hash;
esc.conditions.hash_lock.preimage_size = o.preimage_size;
if ( o.extensions.value.memo.valid() )
esc.memo = o.extensions.value.memo;
esc.conditions.time_lock.expiration = dbase.head_block_time() + o.claim_period_seconds;
});
return esc.id;
Expand All @@ -99,9 +137,10 @@ namespace graphene {

void_result htlc_redeem_evaluator::do_evaluate(const htlc_redeem_operation& o)
{
htlc_obj = &db().get<htlc_object>(o.htlc_id);
auto& d = db();
htlc_obj = &d.get<htlc_object>(o.htlc_id);
detail::check_htlc_redeem_hf_bsip64(d.head_block_time(), o, htlc_obj);

FC_ASSERT(o.preimage.size() == htlc_obj->conditions.hash_lock.preimage_size, "Preimage size mismatch.");
const htlc_redeem_visitor vtor( o.preimage );
FC_ASSERT( htlc_obj->conditions.hash_lock.preimage_hash.visit( vtor ),
"Provided preimage does not generate correct hash.");
Expand Down
2 changes: 2 additions & 0 deletions libraries/chain/include/graphene/chain/htlc_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ namespace graphene { namespace chain {
} time_lock;
} conditions;

fc::optional<memo_data> memo;

/****
* Index helper for timelock
*/
Expand Down
10 changes: 9 additions & 1 deletion libraries/chain/proposal_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,16 @@
#include <graphene/chain/proposal_evaluator.hpp>
#include <graphene/chain/proposal_object.hpp>
#include <graphene/chain/hardfork.hpp>
#include <graphene/chain/htlc_object.hpp>

namespace graphene { namespace chain {

namespace detail {
void check_asset_options_hf_1774(const fc::time_point_sec& block_time, const asset_options& options);
void check_asset_options_hf_1774(const fc::time_point_sec& block_time, const asset_options& options);
void check_htlc_create_hf_bsip64(const fc::time_point_sec& block_time, const htlc_create_operation& op,
abitmore marked this conversation as resolved.
Show resolved Hide resolved
const asset_object& asset);
void check_htlc_redeem_hf_bsip64(const fc::time_point_sec& block_time,
const htlc_redeem_operation& op, const htlc_object* htlc_obj);
void check_asset_options_hf_bsip81(const fc::time_point_sec& block_time, const asset_options& options);
}

Expand Down Expand Up @@ -89,9 +94,12 @@ struct proposal_operation_hardfork_visitor
}
void operator()(const graphene::chain::htlc_create_operation &op) const {
FC_ASSERT( block_time >= HARDFORK_CORE_1468_TIME, "Not allowed until hardfork 1468" );
detail::check_htlc_create_hf_bsip64(block_time, op, op.amount.asset_id(db));
abitmore marked this conversation as resolved.
Show resolved Hide resolved
}
void operator()(const graphene::chain::htlc_redeem_operation &op) const {
FC_ASSERT( block_time >= HARDFORK_CORE_1468_TIME, "Not allowed until hardfork 1468" );
const auto* htlc_obj = &op.htlc_id(db);
detail::check_htlc_redeem_hf_bsip64(block_time, op, htlc_obj);
abitmore marked this conversation as resolved.
Show resolved Hide resolved
}
void operator()(const graphene::chain::htlc_extend_operation &op) const {
FC_ASSERT( block_time >= HARDFORK_CORE_1468_TIME, "Not allowed until hardfork 1468" );
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/small_objects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::htlc_object::condition_info::ti
FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::htlc_object::condition_info, BOOST_PP_SEQ_NIL,
(hash_lock)(time_lock) )
FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::htlc_object, (graphene::db::object),
(transfer) (conditions) )
(transfer) (conditions) (memo) )

FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::operation_history_object, (graphene::chain::object),
(op)(result)(block_num)(trx_in_block)(op_in_trx)(virtual_op) )
Expand Down
14 changes: 14 additions & 0 deletions libraries/protocol/fee_schedule_calc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,20 @@ namespace graphene { namespace protocol {
}
};

/**
* Specialization for htlc_create_operation
*
* For HTLCs, after HF_BSIP64, we need to add in the fee per kb
*/
template<>
uint64_t calc_fee_visitor::operator()(const htlc_create_operation& op)const
{
transfer_operation::fee_parameters_type t;
jmjatlanta marked this conversation as resolved.
Show resolved Hide resolved
if (param.exists<transfer_operation>())
t = param.get<transfer_operation>();
jmjatlanta marked this conversation as resolved.
Show resolved Hide resolved
return op.calculate_fee( param.get<htlc_create_operation>(), t.price_per_kbyte).value;
}

asset fee_schedule::calculate_fee( const operation& op )const
{
uint64_t required_fee = op.visit( calc_fee_visitor( *this, op ) );
Expand Down
10 changes: 6 additions & 4 deletions libraries/protocol/htlc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@ namespace graphene { namespace protocol {
FC_ASSERT( amount.amount > 0, "HTLC amount should be greater than zero" );
}

share_type htlc_create_operation::calculate_fee( const fee_parameters_type& fee_params )const
share_type htlc_create_operation::calculate_fee( const fee_parameters_type& fee_params, uint32_t fee_per_kb )const
{
uint64_t days = ( claim_period_seconds + SECONDS_PER_DAY - 1 ) / SECONDS_PER_DAY;
// multiply with overflow check
uint64_t per_day_fee = fee_params.fee_per_day * days;
FC_ASSERT( days == 0 || per_day_fee / days == fee_params.fee_per_day, "Fee calculation overflow" );
return fee_params.fee + per_day_fee;
share_type total_fee = fee_params.fee;
total_fee += share_type(fee_params.fee_per_day) * days;
if (extensions.value.memo.valid())
total_fee += calculate_data_fee( fc::raw::pack_size(extensions.value.memo), fee_per_kb);
return total_fee;
}

void htlc_redeem_operation::validate()const {
Expand Down
22 changes: 17 additions & 5 deletions libraries/protocol/include/graphene/protocol/htlc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,20 @@
#include <fc/time.hpp>
#include <graphene/protocol/base.hpp>
#include <graphene/protocol/asset.hpp>
#include <graphene/protocol/memo.hpp>
#include <algorithm> // std::max

namespace graphene { namespace protocol {
typedef fc::ripemd160 htlc_algo_ripemd160;
typedef fc::sha1 htlc_algo_sha1;
typedef fc::sha256 htlc_algo_sha256;
typedef fc::hash160 htlc_algo_hash160;

typedef fc::static_variant<
htlc_algo_ripemd160,
htlc_algo_sha1,
htlc_algo_sha256
htlc_algo_sha256,
htlc_algo_hash160
> htlc_hash;

struct htlc_create_operation : public base_operation
Expand All @@ -45,6 +48,7 @@ namespace graphene { namespace protocol {
uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION;
uint64_t fee_per_day = 1 * GRAPHENE_BLOCKCHAIN_PRECISION;
};

// paid to network
asset fee;
// where the held monies are to come from
Expand All @@ -59,8 +63,13 @@ namespace graphene { namespace protocol {
uint16_t preimage_size;
// The time the funds will be returned to the source if not claimed
uint32_t claim_period_seconds;
// for future expansion
extensions_type extensions;

// additional extensions
struct additional_options_type
{
fc::optional<memo_data> memo;
};
abitmore marked this conversation as resolved.
Show resolved Hide resolved
extension<additional_options_type> extensions;

/***
* @brief Does simple validation of this object
Expand All @@ -75,7 +84,7 @@ namespace graphene { namespace protocol {
/****
* @brief calculates the fee to be paid for this operation
*/
share_type calculate_fee(const fee_parameters_type& fee_params)const;
share_type calculate_fee(const fee_parameters_type& fee_params, uint32_t fee_per_kb)const;
};

struct htlc_redeem_operation : public base_operation
Expand Down Expand Up @@ -137,6 +146,7 @@ namespace graphene { namespace protocol {
uint16_t htlc_preimage_size;

asset fee;
std::vector<char> preimage;
jmjatlanta marked this conversation as resolved.
Show resolved Hide resolved
};

struct htlc_extend_operation : public base_operation
Expand Down Expand Up @@ -206,6 +216,7 @@ namespace graphene { namespace protocol {
FC_REFLECT_TYPENAME( graphene::protocol::htlc_hash )

FC_REFLECT( graphene::protocol::htlc_create_operation::fee_parameters_type, (fee) (fee_per_day) )
FC_REFLECT( graphene::protocol::htlc_create_operation::additional_options_type, (memo))
FC_REFLECT( graphene::protocol::htlc_redeem_operation::fee_parameters_type, (fee) (fee_per_kb) )
FC_REFLECT( graphene::protocol::htlc_redeemed_operation::fee_parameters_type, ) // VIRTUAL
FC_REFLECT( graphene::protocol::htlc_extend_operation::fee_parameters_type, (fee) (fee_per_day))
Expand All @@ -215,12 +226,13 @@ FC_REFLECT( graphene::protocol::htlc_create_operation,
(fee)(from)(to)(amount)(preimage_hash)(preimage_size)(claim_period_seconds)(extensions))
FC_REFLECT( graphene::protocol::htlc_redeem_operation, (fee)(htlc_id)(redeemer)(preimage)(extensions))
FC_REFLECT( graphene::protocol::htlc_redeemed_operation,
(fee)(htlc_id)(from)(to)(redeemer)(amount)(htlc_preimage_hash)(htlc_preimage_size))
(fee)(htlc_id)(from)(to)(redeemer)(amount)(htlc_preimage_hash)(htlc_preimage_size)(preimage))
FC_REFLECT( graphene::protocol::htlc_extend_operation, (fee)(htlc_id)(update_issuer)(seconds_to_add)(extensions))
FC_REFLECT( graphene::protocol::htlc_refund_operation,
(fee)(htlc_id)(to)(original_htlc_recipient)(htlc_amount)(htlc_preimage_hash)(htlc_preimage_size))

GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_create_operation::fee_parameters_type )
GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_create_operation::additional_options_type )
abitmore marked this conversation as resolved.
Show resolved Hide resolved
GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_redeem_operation::fee_parameters_type )
GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_extend_operation::fee_parameters_type )
GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_create_operation )
Expand Down
1 change: 1 addition & 0 deletions libraries/protocol/include/graphene/protocol/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <fc/crypto/sha1.hpp>
#include <fc/crypto/sha224.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/crypto/hash160.hpp>
#include <fc/crypto/elliptic.hpp>
#include <fc/reflect/reflect.hpp>
#include <fc/reflect/variant.hpp>
Expand Down
3 changes: 2 additions & 1 deletion libraries/wallet/include/graphene/wallet/wallet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1446,12 +1446,13 @@ class wallet_api
* @param preimage_hash the hash of the preimage
* @param preimage_size the size of the preimage in bytes
* @param claim_period_seconds how long after creation until the lock expires
* @param memo the memo
* @param broadcast true if you wish to broadcast the transaction
* @return the signed transaction
*/
signed_transaction htlc_create( string source, string destination, string amount, string asset_symbol,
string hash_algorithm, const std::string& preimage_hash, uint32_t preimage_size,
const uint32_t claim_period_seconds, bool broadcast = false );
const uint32_t claim_period_seconds, const std::string& memo, bool broadcast = false );

/****
* Update a hashed time lock contract
Expand Down
Loading