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 4 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: 2 additions & 2 deletions libraries/chain/htlc_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ namespace graphene {
// 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 )
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
Expand Down Expand Up @@ -92,7 +92,7 @@ namespace graphene {
( "asset", asset_to_transfer.id )( "acct", from_account.id ) );
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 ) );
( "asset", asset_to_transfer.id )( "acct", to_account.id ) );
return void_result();
}

Expand Down
2 changes: 1 addition & 1 deletion libraries/protocol/fee_schedule_calc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ namespace graphene { namespace protocol {
template<>
uint64_t calc_fee_visitor::operator()(const htlc_create_operation& op)const
{
transfer_operation::fee_parameters_type t;
transfer_operation::fee_parameters_type t = param.get<transfer_operation>();
abitmore marked this conversation as resolved.
Show resolved Hide resolved
return op.calculate_fee( param.get<htlc_create_operation>(), t.price_per_kbyte).value;
}

Expand Down
9 changes: 4 additions & 5 deletions libraries/protocol/htlc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,11 @@ namespace graphene { namespace protocol {
{
uint64_t days = ( claim_period_seconds + SECONDS_PER_DAY - 1 ) / SECONDS_PER_DAY;
// multiply with overflow check
share_type per_day_fee = fee_params.fee_per_day * days;
share_type per_kb_fee = 0;
share_type total_fee = fee_params.fee;
total_fee += share_type(fee_params.fee_per_day) * days;
if (extensions.value.memo.valid())
per_kb_fee = calculate_data_fee( fc::raw::pack_size(extensions.value.memo), 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 + per_kb_fee;
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
56 changes: 31 additions & 25 deletions libraries/wallet/operation_printer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,32 @@ string operation_printer::print_memo( const fc::optional<graphene::protocol::mem
return outstr;
}

void operation_printer::print_preimage(const std::vector<char>& preimage)const
{
if (preimage.size() == 0)
return;
out << " with preimage \"";
// cut it at 50 bytes max
auto flags = out.flags();
out << std::hex << setw(2) << setfill('0');
for (size_t i = 0; i < std::min<size_t>(50, preimage.size()); i++)
out << +preimage[i];
out.flags(flags);
if (preimage.size() > 50)
out << "...(truncated due to size)";
out << "\"";
}

string operation_printer::print_redeem(const graphene::protocol::htlc_id_type& id,
const std::string& redeemer, const std::vector<char>& preimage,
const graphene::protocol::asset& op_fee)const
{
out << redeemer << " redeemed HTLC with id "
<< std::string( static_cast<object_id_type>(id));
print_preimage( preimage );
return fee(op_fee);
}

std::string operation_printer::operator()(const transfer_from_blind_operation& op)const
{
auto a = wallet.get_asset( op.fee.asset_id );
Expand Down Expand Up @@ -146,34 +172,12 @@ std::string operation_printer::operator()(const asset_create_operation& op) cons

std::string operation_printer::operator()(const htlc_redeem_operation& op) const
{
jmjatlanta marked this conversation as resolved.
Show resolved Hide resolved
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);
return print_redeem(op.htlc_id, wallet.get_account(op.redeemer).name, op.preimage, 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);
return print_redeem(op.htlc_id, wallet.get_account(op.redeemer).name, op.preimage, op.fee);
}

std::string operation_printer::operator()(const htlc_create_operation& op) const
Expand All @@ -182,10 +186,12 @@ std::string operation_printer::operator()(const htlc_create_operation& op) const

auto fee_asset = wallet.get_asset( op.fee.asset_id );
auto to = wallet.get_account( op.to );
auto from = wallet.get_account( op.from );
operation_result_printer rprinter(wallet);
std::string database_id = result.visit(rprinter);

out << "Create HTLC to " << to.name << " with id " << database_id
out << "Create HTLC from " << from.name << " to " << to.name
<< " with id " << database_id
<< " preimage hash: [" << op.preimage_hash.visit( vtor ) << "] ";
print_memo( op.extensions.value.memo );
// determine if the block that the HTLC is in is before or after LIB
Expand Down
4 changes: 4 additions & 0 deletions libraries/wallet/operation_printer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ struct operation_printer
std::string operator()(const graphene::protocol::htlc_redeemed_operation& op)const;
protected:
std::string print_memo( const fc::optional<graphene::protocol::memo_data>& memo)const;
void print_preimage( const std::vector<char>& preimage)const;
std::string print_redeem(const graphene::protocol::htlc_id_type& id,
const std::string& redeemer, const std::vector<char>& preimage,
const graphene::protocol::asset& op_fee)const;
};

}}} // namespace graphene::wallet::detail
67 changes: 33 additions & 34 deletions tests/cli/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1686,7 +1686,7 @@ BOOST_AUTO_TEST_CASE( cli_create_htlc_bsip64 )

BOOST_TEST_MESSAGE("Alice has agreed to buy 3 BOBCOIN from Bob for 3 BTS. Alice creates an HTLC");
// create an HTLC
std::string preimage_string = "My Secret";
std::string preimage_string = "My Super Long Secret that is larger than 50 charaters. How do I look?\n";
fc::hash160 preimage_md = fc::hash160::hash(preimage_string);
std::stringstream ss;
for(size_t i = 0; i < preimage_md.data_size(); i++)
Expand Down Expand Up @@ -1735,35 +1735,6 @@ BOOST_AUTO_TEST_CASE( cli_create_htlc_bsip64 )
htlc_id_type htlc_id = result_block.transactions[result_block.transactions.size()-1].operation_results[0].get<object_id_type>();
bob_htlc_id_as_string = (std::string)(object_id_type)htlc_id;
BOOST_TEST_MESSAGE("Bob shares the HTLC ID with Alice. The HTLC ID is: " + bob_htlc_id_as_string);
// test operation_printer
auto hist = con.wallet_api_ptr->get_account_history("alice", 10);
for(size_t i = 0; i < hist.size(); ++i)
{
auto obj = hist[i];
std::stringstream ss;
ss << "Description: " << obj.description << "\n";
auto str = ss.str();
BOOST_TEST_MESSAGE( str );
if (i < 2)
{
BOOST_CHECK( str.find("HASH160 008e") != std::string::npos );
}
}
con.wallet_api_ptr->lock();
hist = con.wallet_api_ptr->get_account_history("alice", 10);
for(size_t i = 0; i < hist.size(); ++i)
{
auto obj = hist[i];
std::stringstream ss;
ss << "Description: " << obj.description << "\n";
auto str = ss.str();
BOOST_TEST_MESSAGE( str );
if (i < 2)
{
BOOST_CHECK( str.find("HASH160 008e") != std::string::npos );
}
}
con.wallet_api_ptr->unlock("supersecret");
}

// Alice can now look over Bob's HTLC, to see if it is what was agreed to:
Expand All @@ -1774,8 +1745,7 @@ BOOST_AUTO_TEST_CASE( cli_create_htlc_bsip64 )
// Alice likes what she sees, so uses her preimage to get her BOBCOIN
{
BOOST_TEST_MESSAGE("Alice uses her preimage to retrieve the BOBCOIN");
std::string secret = "My Secret";
con.wallet_api_ptr->htlc_redeem(bob_htlc_id_as_string, "alice", secret, true);
con.wallet_api_ptr->htlc_redeem(bob_htlc_id_as_string, "alice", preimage_string, true);
BOOST_TEST_MESSAGE("The system is generating a block");
BOOST_CHECK(generate_block(app1));
}
Expand All @@ -1784,12 +1754,41 @@ BOOST_AUTO_TEST_CASE( cli_create_htlc_bsip64 )
// Bob can use the preimage to retrieve his BTS
{
BOOST_TEST_MESSAGE("Bob uses Alice's preimage to retrieve the BOBCOIN");
std::string secret = "My Secret";
con.wallet_api_ptr->htlc_redeem(alice_htlc_id_as_string, "bob", secret, true);
con.wallet_api_ptr->htlc_redeem(alice_htlc_id_as_string, "bob", preimage_string, true);
BOOST_TEST_MESSAGE("The system is generating a block");
BOOST_CHECK(generate_block(app1));
}

// test operation_printer
auto hist = con.wallet_api_ptr->get_account_history("alice", 10);
for(size_t i = 0; i < hist.size(); ++i)
{
auto obj = hist[i];
std::stringstream ss;
ss << "Description: " << obj.description << "\n";
auto str = ss.str();
BOOST_TEST_MESSAGE( str );
if (i == 3 || i == 4)
{
BOOST_CHECK( str.find("HASH160 620e4d5ba") != std::string::npos );
}
}
con.wallet_api_ptr->lock();
hist = con.wallet_api_ptr->get_account_history("alice", 10);
for(size_t i = 0; i < hist.size(); ++i)
{
auto obj = hist[i];
std::stringstream ss;
ss << "Description: " << obj.description << "\n";
auto str = ss.str();
BOOST_TEST_MESSAGE( str );
if (i == 3 || i == 4)
{
BOOST_CHECK( str.find("HASH160 620e4d5ba") != std::string::npos );
}
}
con.wallet_api_ptr->unlock("supersecret");

// wait for everything to finish up
fc::usleep(fc::seconds(1));
} catch( fc::exception& e ) {
Expand Down
6 changes: 6 additions & 0 deletions tests/common/database_fixture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1457,6 +1457,12 @@ flat_map< uint64_t, graphene::chain::fee_parameters > database_fixture::get_htlc
extend_param.fee_per_day = 2 * GRAPHENE_BLOCKCHAIN_PRECISION;
ret_val[((operation)htlc_extend_operation()).which()] = extend_param;

// set the transfer kb fee to something other than default, to verify we're looking
// at the correct fee
transfer_operation::fee_parameters_type transfer_param;
transfer_param.price_per_kbyte *= 2;
ret_val[ ((operation)transfer_operation()).which() ] = transfer_param;

return ret_val;
}

Expand Down
6 changes: 3 additions & 3 deletions tests/tests/htlc_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,8 @@ try {
generate_block();
}

// verify funds on hold... 100 - 3 = 97, minus the transaction fee = 91.78907
BOOST_CHECK_EQUAL( get_balance(alice_id, graphene::chain::asset_id_type()), 91.78907 * GRAPHENE_BLOCKCHAIN_PRECISION );
// verify funds on hold... 100 - 3 = 97, minus the transaction fee = 90.57813
BOOST_CHECK_EQUAL( get_balance(alice_id, graphene::chain::asset_id_type()), 90.57813 * GRAPHENE_BLOCKCHAIN_PRECISION );
jmjatlanta marked this conversation as resolved.
Show resolved Hide resolved

// make sure Bob (or anyone) can see the details of the transaction
graphene::app::database_api db_api(db);
Expand Down Expand Up @@ -389,7 +389,7 @@ try {
// verify funds end up in Bob's account (3)
BOOST_CHECK_EQUAL( get_balance(bob_id, graphene::chain::asset_id_type()), 3 * GRAPHENE_BLOCKCHAIN_PRECISION );
// verify funds remain out of Alice's acount ( 100 - 3 - transaction fee )
BOOST_CHECK_EQUAL( get_balance(alice_id, graphene::chain::asset_id_type()), 91.78907 * GRAPHENE_BLOCKCHAIN_PRECISION );
BOOST_CHECK_EQUAL( get_balance(alice_id, graphene::chain::asset_id_type()), 90.57813 * GRAPHENE_BLOCKCHAIN_PRECISION );
// verify all three get notified
std::vector<operation_history_object> history = get_operation_history(alice_id);
BOOST_CHECK_EQUAL( history.size(), alice_num_history + 1);
Expand Down