BitShares-Core  4.0.0
BitShares blockchain implementation and command-line interface software
htlc_evaluator.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 jmjatlanta and contributors.
3  *
4  * The MIT License
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
27 #include <graphene/chain/hardfork.hpp>
29 
30 namespace graphene {
31  namespace chain {
32  namespace detail
33  {
35  const htlc_create_operation& op, const asset_object& asset_to_transfer)
36  {
37  if (block_time < HARDFORK_CORE_BSIP64_TIME)
38  {
39  // memo field added at harfork BSIP64
40  // NOTE: both of these checks can be removed after hardfork time
41  FC_ASSERT( !op.extensions.value.memo.valid(),
42  "Memo unavailable until after HARDFORK BSIP64");
43  // HASH160 added at hardfork BSIP64
45  "HASH160 unavailable until after HARDFORK BSIP64" );
46  }
47  else
48  {
49  // this can be moved to the normal non-hf checks after HF_BSIP64
50  // IF there were no restricted transfers before HF_BSIP64
51  FC_ASSERT( !asset_to_transfer.is_transfer_restricted()
52  || op.from == asset_to_transfer.issuer || op.to == asset_to_transfer.issuer,
53  "Asset ${asset} cannot be transfered.", ("asset", asset_to_transfer.id) );
54  }
55  }
56 
58  const htlc_redeem_operation& op, const htlc_object* htlc_obj)
59  {
60  // TODO: The hardfork portion of this check can be removed if no HTLC redemptions are
61  // attempted on an HTLC with a 0 preimage size before the hardfork date.
62  if ( htlc_obj->conditions.hash_lock.preimage_size > 0U ||
63  block_time < HARDFORK_CORE_BSIP64_TIME )
64  FC_ASSERT(op.preimage.size() == htlc_obj->conditions.hash_lock.preimage_size,
65  "Preimage size mismatch.");
66  }
67  } // end of graphene::chain::details
68 
70  {
71  return db.get_global_properties().parameters.extensions.value.updatable_htlc_options;
72  }
73 
75  {
76  graphene::chain::database& d = db();
78 
79  FC_ASSERT(htlc_options, "HTLC Committee options are not set.");
80 
81  // make sure the expiration is reasonable
82  FC_ASSERT( o.claim_period_seconds <= htlc_options->max_timeout_secs,
83  "HTLC Timeout exceeds allowed length" );
84  // make sure the preimage length is reasonable
85  FC_ASSERT( o.preimage_size <= htlc_options->max_preimage_size,
86  "HTLC preimage length exceeds allowed length" );
87  // make sure the sender has the funds for the HTLC
88  FC_ASSERT( d.get_balance( o.from, o.amount.asset_id) >= (o.amount), "Insufficient funds") ;
89  const auto& asset_to_transfer = o.amount.asset_id( d );
90  const auto& from_account = o.from( d );
91  const auto& to_account = o.to( d );
92  detail::check_htlc_create_hf_bsip64(d.head_block_time(), o, asset_to_transfer);
93  FC_ASSERT( is_authorized_asset( d, from_account, asset_to_transfer ),
94  "Asset ${asset} is not authorized for account ${acct}.",
95  ( "asset", asset_to_transfer.id )( "acct", from_account.id ) );
96  FC_ASSERT( is_authorized_asset( d, to_account, asset_to_transfer ),
97  "Asset ${asset} is not authorized for account ${acct}.",
98  ( "asset", asset_to_transfer.id )( "acct", to_account.id ) );
99  return void_result();
100  }
101 
103  {
104  try {
105  graphene::chain::database& dbase = db();
106  dbase.adjust_balance( o.from, -o.amount );
107 
108  const htlc_object& esc = db().create<htlc_object>([&dbase,&o]( htlc_object& esc ) {
109  esc.transfer.from = o.from;
110  esc.transfer.to = o.to;
111  esc.transfer.amount = o.amount.amount;
115  if ( o.extensions.value.memo.valid() )
116  esc.memo = o.extensions.value.memo;
117  esc.conditions.time_lock.expiration = dbase.head_block_time() + o.claim_period_seconds;
118  });
119  return esc.id;
120 
121  } FC_CAPTURE_AND_RETHROW( (o) )
122  }
123 
125  {
126  //private:
127  const std::vector<char>& data;
128  public:
129  typedef bool result_type;
130 
131  htlc_redeem_visitor( const std::vector<char>& preimage )
132  : data( preimage ) {}
133 
134  template<typename T>
135  bool operator()( const T& preimage_hash )const
136  {
137  return T::hash( (const char*)data.data(), (uint32_t) data.size() ) == preimage_hash;
138  }
139  };
140 
142  {
143  auto& d = db();
144  htlc_obj = &d.get<htlc_object>(o.htlc_id);
145  detail::check_htlc_redeem_hf_bsip64(d.head_block_time(), o, htlc_obj);
146 
147  const htlc_redeem_visitor vtor( o.preimage );
148  FC_ASSERT( htlc_obj->conditions.hash_lock.preimage_hash.visit( vtor ),
149  "Provided preimage does not generate correct hash.");
150 
151  return void_result();
152  }
153 
155  {
156  const auto amount = asset(htlc_obj->transfer.amount, htlc_obj->transfer.asset_id);
157  db().adjust_balance(htlc_obj->transfer.to, amount);
158  // notify related parties
159  htlc_redeemed_operation virt_op( htlc_obj->id, htlc_obj->transfer.from, htlc_obj->transfer.to, o.redeemer,
160  amount, htlc_obj->conditions.hash_lock.preimage_hash, htlc_obj->conditions.hash_lock.preimage_size,
161  o.preimage );
162  db().push_applied_operation( virt_op );
163  db().remove(*htlc_obj);
164  return void_result();
165  }
166 
168  {
169  htlc_obj = &db().get<htlc_object>(o.htlc_id);
170  FC_ASSERT(o.update_issuer == htlc_obj->transfer.from, "HTLC may only be extended by its creator.");
172  FC_ASSERT( htlc_obj->conditions.time_lock.expiration.sec_since_epoch()
173  + static_cast<uint64_t>(o.seconds_to_add) < fc::time_point_sec::maximum().sec_since_epoch(),
174  "Extension would cause an invalid date");
175  FC_ASSERT( htlc_obj->conditions.time_lock.expiration + o.seconds_to_add
176  <= db().head_block_time() + htlc_options->max_timeout_secs,
177  "Extension pushes contract too far into the future" );
178  return void_result();
179  }
180 
182  {
183  db().modify(*htlc_obj, [&o](htlc_object& db_obj) {
185  });
186 
187  return void_result();
188  }
189 
190  } // namespace chain
191 } // namespace graphene
bool is_type() const
struct graphene::chain::htlc_object::transfer_info transfer
struct graphene::chain::htlc_object::condition_info::time_lock_info time_lock
void adjust_balance(account_id_type account, asset delta)
Adjust a particular account&#39;s balance in a given asset by a delta.
Definition: db_balance.cpp:54
database object to store HTLCs
Definition: htlc_object.hpp:40
bool is_authorized_asset(const database &d, const account_object &acct, const asset_object &asset_obj)
struct graphene::chain::htlc_object::condition_info conditions
uint32_t sec_since_epoch() const
Definition: time.hpp:90
tracks the blockchain state in an extensible manner
Definition: database.hpp:70
Definition: api.cpp:56
asset get_balance(account_id_type owner, asset_id_type asset_id) const
Retrieve a particular account&#39;s balance in a given asset.
Definition: db_balance.cpp:35
htlc_redeem_visitor(const std::vector< char > &preimage)
void_result do_apply(const htlc_redeem_operation &o)
account_id_type issuer
ID of the account which issued this asset.
const global_property_object & get_global_properties() const
Definition: db_getter.cpp:44
provides stack-based nullable value similar to boost::optional
Definition: optional.hpp:20
void check_htlc_redeem_hf_bsip64(const fc::time_point_sec &block_time, const htlc_redeem_operation &op, const htlc_object *htlc_obj)
extension< additional_options_type > extensions
Definition: htlc.hpp:72
void_result do_evaluate(const htlc_create_operation &o)
void_result do_apply(const htlc_extend_operation &o)
fc::optional< memo_data > memo
Definition: htlc_object.hpp:62
object_id_type do_apply(const htlc_create_operation &o)
static time_point_sec maximum()
Definition: time.hpp:86
object_id_type id
Definition: object.hpp:73
time_point_sec head_block_time() const
Definition: db_getter.cpp:64
optional< htlc_options > get_committee_htlc_options(graphene::chain::database &db)
void check_htlc_create_hf_bsip64(const fc::time_point_sec &block_time, const htlc_create_operation &op, const asset_object &asset_to_transfer)
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:478
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
void_result do_evaluate(const htlc_redeem_operation &o)
tracks the parameters of an assetAll assets have a globally unique symbol name that controls how they...
asset_id_type asset_id
Definition: asset.hpp:39
struct graphene::chain::htlc_object::condition_info::hash_lock_info hash_lock
bool operator()(const T &preimage_hash) const
void_result do_evaluate(const htlc_extend_operation &o)
bool is_transfer_restricted() const