Scorum
atomicswap.cpp
Go to the documentation of this file.
7 
9 
10 using namespace scorum::protocol;
11 
12 namespace scorum {
13 namespace chain {
14 
15 dbs_atomicswap::dbs_atomicswap(database& db)
16  : base_service_type(db)
17  , _dgp_svc(db.dynamic_global_property_service())
18  , _account_svc(db.account_service())
19 {
20 }
21 
23 {
25 
26  const auto& idx = db_impl().get_index<atomicswap_contract_index>().indices().get<by_owner_name>();
27 
28  std::copy(idx.cbegin(), idx.cend(), std::back_inserter(ret));
29 
30  return ret;
31 }
32 
34 {
36 
37  const auto& idx
38  = db_impl().get_index<atomicswap_contract_index>().indices().get<by_owner_name>().equal_range(owner.name);
39  for (auto it = idx.first; it != idx.second; ++it)
40  {
41  ret.push_back(std::cref(*it));
42  }
43 
44  return ret;
45 }
46 
47 const atomicswap_contract_object&
48 dbs_atomicswap::get_contract(const account_object& from, const account_object& to, const std::string& secret_hash) const
49 {
50  FC_ASSERT(!secret_hash.empty(), "Empty secret hash.");
51 
52  try
53  {
54  atomicswap::hash_index_type contract_hash = atomicswap::get_contract_hash(from.name, to.name, secret_hash);
55  return get_by<by_contract_hash>(contract_hash);
56  }
57  FC_CAPTURE_AND_RETHROW((from.name)(to.name)(secret_hash))
58 }
59 
60 const atomicswap_contract_object& dbs_atomicswap::create_contract(atomicswap_contract_type tp,
61  const account_object& owner,
62  const account_object& recipient,
63  const asset& amount,
64  const std::string& secret_hash,
65  const optional<std::string>& metadata)
66 {
67  FC_ASSERT(amount.symbol() == SCORUM_SYMBOL, "Invalid asset type (symbol).");
68  FC_ASSERT(amount.amount > 0, "Invalid amount.");
69  FC_ASSERT(owner.balance >= amount, "Insufficient funds.");
70  FC_ASSERT(!secret_hash.empty(), "Empty secret hash.");
71 
72  atomicswap::hash_index_type contract_hash = atomicswap::get_contract_hash(owner.name, recipient.name, secret_hash);
73 
74  FC_ASSERT((nullptr == find_by<by_contract_hash>(contract_hash)),
75  "There is contract for '${a}' with same secret. Use another secret and try again.",
76  ("a", recipient.name));
78  "Can't create more then ${1} contract per owner.",
80  FC_ASSERT(_contracts_per_recipient(owner.name, recipient.name)
82  "Can't create more then ${1} contract per recipient.",
84 
85  time_point_sec start = _dgp_svc.head_block_time();
86  time_point_sec deadline = start;
87  switch (tp)
88  {
89  case atomicswap_contract_initiator:
90  deadline += fc::seconds(SCORUM_ATOMICSWAP_INITIATOR_REFUND_LOCK_SECS);
91  break;
92  case atomicswap_contract_participant:
93  deadline += fc::seconds(SCORUM_ATOMICSWAP_PARTICIPANT_REFUND_LOCK_SECS);
94  break;
95  default:
96  FC_ASSERT(false, "Invalid contract type.");
97  }
98 
99  const atomicswap_contract_object& new_contract = create([&](atomicswap_contract_object& contract) {
100  contract.type = tp;
101  contract.owner = owner.name;
102  contract.to = recipient.name;
103  contract.amount = amount;
104  contract.created = start;
105  contract.deadline = deadline;
106  fc::from_string(contract.secret_hash, secret_hash);
107  contract.contract_hash = contract_hash;
108  if (metadata.valid())
109  {
110  fc::from_string(contract.metadata, *metadata);
111  }
112  });
113 
114  _account_svc.decrease_balance(owner, amount);
115 
116  return new_contract;
117 }
118 
119 void dbs_atomicswap::redeem_contract(const atomicswap_contract_object& contract, const std::string& secret)
120 {
121  const account_object& to = _account_svc.get_account(contract.to);
122 
123  _account_svc.increase_balance(to, contract.amount);
124 
125  if (contract.type == atomicswap_contract_initiator)
126  {
127  remove(contract);
128  }
129  else
130  {
131  // save secret for participant
132  update(contract, [&](atomicswap_contract_object& contract) {
133  fc::from_string(contract.secret, secret);
134  contract.amount.amount = 0; // asset moved to 'to' balance
135  });
136  }
137 }
138 
139 void dbs_atomicswap::refund_contract(const atomicswap_contract_object& contract)
140 {
141  const account_object& owner = _account_svc.get_account(contract.owner);
142 
143  _account_svc.increase_balance(owner, contract.amount);
144 
145  remove(contract);
146 }
147 
148 std::size_t dbs_atomicswap::_contracts_per_recipient(const account_name_type& owner,
149  const account_name_type& recipient) const
150 {
151  return db_impl().get_index<atomicswap_contract_index>().indices().get<by_recipient_name>().count(recipient);
152 }
153 
154 } // namespace chain
155 } // namespace scorum
tracks the blockchain state in an extensible manner
Definition: database.hpp:52
virtual const atomicswap_contract_object & get_contract(const account_object &from, const account_object &to, const std::string &secret_hash) const override
Definition: atomicswap.cpp:48
virtual atomicswap_contracts_refs_type get_contracts() const override
Definition: atomicswap.cpp:22
virtual void refund_contract(const atomicswap_contract_object &contract) override
Definition: atomicswap.cpp:139
virtual const atomicswap_contract_object & create_contract(atomicswap_contract_type tp, const account_object &owner, const account_object &recipient, const asset &amount, const std::string &secret_hash, const optional< std::string > &metadata=optional< std::string >()) override
Definition: atomicswap.cpp:60
virtual void redeem_contract(const atomicswap_contract_object &contract, const std::string &secret) override
Definition: atomicswap.cpp:119
dba::db_index & db_impl()
Definition: dbs_base.cpp:22
virtual const object_type & create(const modifier_type &modifier) override
virtual void update(const modifier_type &modifier) override
#define SCORUM_ATOMICSWAP_INITIATOR_REFUND_LOCK_SECS
Definition: config.hpp:149
#define SCORUM_SYMBOL
Definition: config.hpp:102
#define SCORUM_ATOMICSWAP_LIMIT_REQUESTED_CONTRACTS_PER_RECIPIENT
Definition: config.hpp:153
#define SCORUM_ATOMICSWAP_LIMIT_REQUESTED_CONTRACTS_PER_OWNER
Definition: config.hpp:152
#define SCORUM_ATOMICSWAP_PARTICIPANT_REFUND_LOCK_SECS
Definition: config.hpp:150
size_t size(db_index &db_idx)
Definition: db_accessor.hpp:25
fc::fixed_string_32 hash_index_type
hash_index_type get_contract_hash(const account_name_type &from, const account_name_type &to, const std::string &secret_hash)
fc::fixed_string_16 account_name_type
Definition: types.hpp:62
Definition: asset.cpp:15
virtual const account_object & get_account(const account_name_type &) const =0
virtual void increase_balance(const account_object &account, const asset &amount)=0
virtual void decrease_balance(const account_object &account, const asset &amount)=0
std::vector< std::reference_wrapper< const atomicswap_contract_object > > atomicswap_contracts_refs_type
Definition: atomicswap.hpp:14
virtual fc::time_point_sec head_block_time() const =0
asset_symbol_type symbol() const
Definition: asset.hpp:32
share_type amount
Definition: asset.hpp:31