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 12 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
18 changes: 16 additions & 2 deletions libraries/chain/htlc_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ namespace graphene {
FC_ASSERT( o.preimage_size <= htlc_options->max_preimage_size, "HTLC preimage length exceeds allowed length" );
// make sure the sender has the funds for the HTLC
FC_ASSERT( d.get_balance( o.from, o.amount.asset_id) >= (o.amount), "Insufficient funds") ;
// memo field added at harfork BSIP64
// NOTE: this check can be removed after hardfork time
FC_ASSERT( d.head_block_time() > HARDFORK_CORE_BSIP64_TIME || !o.extensions.value.memo.valid(),
"Memo unavailable until after HARDFORK BSIP64");
// HASH160 added at hardfork BSIP64
FC_ASSERT( d.head_block_time() > HARDFORK_CORE_BSIP64_TIME || o.preimage_hash.which() !=
htlc_hash(fc::hash160()).which(), "HASH160 unavailable until after HARDFORK BSIP64" );
const auto& asset_to_transfer = o.amount.asset_id( d );
const auto& from_account = o.from( d );
const auto& to_account = o.to( d );
Expand All @@ -57,6 +64,8 @@ namespace graphene {
FC_ASSERT( is_authorized_asset( d, to_account, asset_to_transfer ),
"Asset ${asset} is not authorized for account ${acct}.",
( "asset", asset_to_transfer.id )( "acct", to_account.id ) );
FC_ASSERT( d.head_block_time() < HARDFORK_CORE_BSIP64_TIME || !asset_to_transfer.is_transfer_restricted(),
"Asset ${asset} cannot be transfered.", ("asset", asset_to_transfer.id) );
return void_result();
}

Expand All @@ -73,6 +82,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 Down Expand Up @@ -100,8 +111,11 @@ namespace graphene {
void_result htlc_redeem_evaluator::do_evaluate(const htlc_redeem_operation& o)
{
htlc_obj = &db().get<htlc_object>(o.htlc_id);

FC_ASSERT(o.preimage.size() == htlc_obj->conditions.hash_lock.preimage_size, "Preimage size mismatch.");
// 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 ||
db().head_block_time() <= HARDFORK_CORE_BSIP64_TIME )
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
5 changes: 5 additions & 0 deletions libraries/chain/proposal_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ struct proposal_operation_hardfork_visitor
FC_ASSERT(!op.new_parameters.current_fees->exists<htlc_redeem_operation>());
FC_ASSERT(!op.new_parameters.current_fees->exists<htlc_extend_operation>());
}
if (block_time < HARDFORK_CORE_BSIP64_TIME)
{
FC_ASSERT( op.new_parameters.current_fees->get<htlc_create_operation>().fee_per_kb == 0,
"Unable to set htlc_create_operation per_kb_fee until after BSIP 64 hardfork");
}
if (!HARDFORK_BSIP_40_PASSED(block_time)) {
FC_ASSERT(!op.new_parameters.extensions.value.custom_authority_options.valid(),
"Unable to set Custom Authority Options before hardfork BSIP 40");
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
5 changes: 4 additions & 1 deletion libraries/protocol/htlc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,11 @@ namespace graphene { namespace protocol {
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;
uint64_t per_kb_fee = 0;
if (extensions.value.memo.valid())
per_kb_fee = calculate_data_fee( fc::raw::pack_size(extensions.value.memo), fee_params.fee_per_kb);
FC_ASSERT( days == 0 || per_day_fee / days == fee_params.fee_per_day, "Fee calculation overflow" );
return fee_params.fee + per_day_fee;
return fee_params.fee + per_day_fee + per_kb_fee;
}

void htlc_redeem_operation::validate()const {
Expand Down
21 changes: 17 additions & 4 deletions libraries/protocol/include/graphene/protocol/htlc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,30 @@
#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
{
struct fee_parameters_type {
uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION;
uint64_t fee_per_day = 1 * GRAPHENE_BLOCKCHAIN_PRECISION;
uint64_t fee_per_kb = 0;
};

// paid to network
asset fee;
// where the held monies are to come from
Expand All @@ -59,8 +64,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;
};
extension<additional_options_type> extensions;

/***
* @brief Does simple validation of this object
Expand Down Expand Up @@ -137,6 +147,7 @@ namespace graphene { namespace protocol {
uint16_t htlc_preimage_size;

asset fee;
std::vector<char> preimage;
};

struct htlc_extend_operation : public base_operation
Expand Down Expand Up @@ -205,7 +216,8 @@ 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::fee_parameters_type, (fee) (fee_per_day) (fee_per_kb) )
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 @@ -221,6 +233,7 @@ 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 )
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
23 changes: 23 additions & 0 deletions libraries/wallet/operation_printer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ class htlc_hash_to_string_visitor
{
return "SHA256 " + hash.str();
}
result_type operator()( const fc::hash160& hash )const
{
return "HASH160 " + hash.str();
}
};

std::string operation_printer::fee(const graphene::protocol::asset& a)const {
Expand Down Expand Up @@ -135,13 +139,32 @@ std::string operation_printer::operator()(const asset_create_operation& op) cons

std::string operation_printer::operator()(const htlc_redeem_operation& op) const
{
auto flags = out.flags();
out << "Redeem HTLC with database id "
<< std::to_string(op.htlc_id.space_id)
<< "." << std::to_string(op.htlc_id.type_id)
<< "." << std::to_string((uint64_t)op.htlc_id.instance)
<< " with preimage \"";
out << std::hex;
for (unsigned char c : op.preimage)
out << c;
out.flags(flags);
out << "\"";
return fee(op.fee);
}

std::string operation_printer::operator()(const htlc_redeemed_operation& op) const
{
auto flags = out.flags();
out << "Redeem HTLC with database id "
<< std::to_string(op.htlc_id.space_id)
<< "." << std::to_string(op.htlc_id.type_id)
<< "." << std::to_string((uint64_t)op.htlc_id.instance)
<< " with preimage \"";
out << std::hex;
for (unsigned char c : op.preimage)
out << c;
out.flags(flags);
out << "\"";
return fee(op.fee);
}
Expand Down
1 change: 1 addition & 0 deletions libraries/wallet/operation_printer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ struct operation_printer
std::string operator()(const graphene::protocol::asset_create_operation& op)const;
std::string operator()(const graphene::protocol::htlc_create_operation& op)const;
std::string operator()(const graphene::protocol::htlc_redeem_operation& op)const;
std::string operator()(const graphene::protocol::htlc_redeemed_operation& op)const;
};

}}} // namespace graphene::wallet::detail
8 changes: 6 additions & 2 deletions libraries/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,10 @@ uint64_t wallet_api::get_asset_count()const

signed_transaction wallet_api::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)
const uint32_t claim_period_seconds, const std::string& memo, bool broadcast)
{
return my->htlc_create(source, destination, amount, asset_symbol, hash_algorithm, preimage_hash, preimage_size,
claim_period_seconds, broadcast);
claim_period_seconds, memo, broadcast);
}

fc::optional<fc::variant> wallet_api::get_htlc(std::string htlc_id) const
Expand All @@ -223,6 +223,8 @@ fc::optional<fc::variant> wallet_api::get_htlc(std::string htlc_id) const
const auto& asset = my->get_asset( obj.transfer.asset_id );
transfer["asset"] = asset.symbol;
transfer["amount"] = graphene::app::uint128_amount_to_string( obj.transfer.amount.value, asset.precision );
if (obj.memo.valid())
transfer["memo"] = my->read_memo( *obj.memo );
class htlc_hash_to_variant_visitor
{
public:
Expand All @@ -234,6 +236,8 @@ fc::optional<fc::variant> wallet_api::get_htlc(std::string htlc_id) const
{ return convert("SHA1", obj.str()); }
result_type operator()(const fc::sha256& obj)const
{ return convert("SHA256", obj.str()); }
result_type operator()(const fc::hash160& obj)const
{ return convert("HASH160", obj.str()); }
private:
result_type convert(const std::string& type, const std::string& hash)const
{
Expand Down
2 changes: 1 addition & 1 deletion libraries/wallet/wallet_api_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ class wallet_api_impl

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 );

signed_transaction htlc_redeem( string htlc_id, string issuer, const std::vector<char>& preimage, bool broadcast );

Expand Down
15 changes: 14 additions & 1 deletion libraries/wallet/wallet_transfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ namespace graphene { namespace wallet { namespace detail {
return fc::sha256( hash );
if( name_upper == "SHA1" )
return fc::sha1( hash );
if( name_upper == "HASH160" )
return fc::hash160( hash );
FC_THROW_EXCEPTION( fc::invalid_arg_exception, "Unknown algorithm '${a}'", ("a",algorithm) );
}

Expand Down Expand Up @@ -83,21 +85,32 @@ namespace graphene { namespace wallet { namespace detail {

signed_transaction wallet_api_impl::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 )
const uint32_t claim_period_seconds, const std::string& memo, bool broadcast )
{
try
{
FC_ASSERT( !self.is_locked() );
fc::optional<asset_object> asset_obj = get_asset(asset_symbol);
FC_ASSERT(asset_obj, "Could not find asset matching ${asset}", ("asset", asset_symbol));

const account_object& from_acct = get_account(source);
const account_object& to_acct = get_account(destination);
htlc_create_operation create_op;
create_op.from = get_account(source).id;
create_op.to = get_account(destination).id;
create_op.amount = asset_obj->amount_from_string(amount);
create_op.claim_period_seconds = claim_period_seconds;
create_op.preimage_hash = do_hash( hash_algorithm, preimage_hash );
create_op.preimage_size = preimage_size;
if (!memo.empty())
{
memo_data data;
data.from = from_acct.options.memo_key;
data.to = to_acct.options.memo_key;
data.set_message(
get_private_key(from_acct.options.memo_key), to_acct.options.memo_key, memo);
create_op.extensions.value.memo = data;
}

signed_transaction tx;
tx.operations.push_back(create_op);
Expand Down
2 changes: 1 addition & 1 deletion programs/build_helpers/member_enumerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ void class_processor::process_class( const static_variant< T... >* dummy )
static_variant<T...> dummy2;
static_variant_visitor vtor( this );

for( int w=0; w<dummy2.count(); w++ )
for( size_t w=0; w<dummy2.count(); w++ )
{
dummy2.set_which(w);
dummy2.visit( vtor );
Expand Down
4 changes: 2 additions & 2 deletions programs/js_operation_serializer/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ struct serializer< fc::static_variant<T...>, false >
{
init = true;
fc::static_variant<T...> var;
for( int i = 0; i < var.count(); ++i )
for( size_t i = 0; i < var.count(); ++i )
{
var.set_which(i);
var.visit( register_type_visitor() );
Expand Down Expand Up @@ -372,7 +372,7 @@ int main( int argc, char** argv )
operation op;

std::cout << "ChainTypes.operations=\n";
for( int i = 0; i < op.count(); ++i )
for( size_t i = 0; i < op.count(); ++i )
{
op.set_which(i);
op.visit( detail_ns::serialize_type_visitor(i) );
Expand Down
2 changes: 1 addition & 1 deletion programs/size_checker/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ int main( int argc, char** argv )

idump( (witnesses) );

for( int32_t i = 0; i < op.count(); ++i )
for( size_t i = 0; i < op.count(); ++i )
{
op.set_which(i);
op.visit( size_check_type_visitor(i) );
Expand Down
Loading