Scorum
transaction.cpp
Go to the documentation of this file.
1 
4 
5 #include <fc/io/raw.hpp>
6 #include <fc/bitutil.hpp>
7 #include <fc/smart_ref_impl.hpp>
8 
9 #include <algorithm>
10 
11 namespace scorum {
12 namespace protocol {
13 
15 {
16  digest_type::encoder enc;
17  fc::raw::pack(enc, *this);
18  return enc.result();
19 }
20 
22 {
23  digest_type::encoder enc;
24  fc::raw::pack(enc, *this);
25  return enc.result();
26 }
27 
29 {
30  digest_type::encoder enc;
31  fc::raw::pack(enc, chain_id);
32  fc::raw::pack(enc, *this);
33  return enc.result();
34 }
35 
37 {
38  FC_ASSERT(operations.size() > 0, "A transaction must have at least one operation", ("trx", *this));
39  for (const auto& op : operations)
41 }
42 
44 {
45  auto h = digest();
47  memcpy(result._hash, h._hash, std::min(sizeof(result), sizeof(h)));
48  return result;
49 }
50 
52  const chain_id_type& chain_id)
53 {
54  digest_type h = sig_digest(chain_id);
55  signatures.push_back(key.sign_compact(h));
56  return signatures.back();
57 }
58 
60  const chain_id_type& chain_id) const
61 {
62  digest_type::encoder enc;
63  fc::raw::pack(enc, chain_id);
64  fc::raw::pack(enc, *this);
65  return key.sign_compact(enc.result());
66 }
67 
68 void transaction::set_expiration(fc::time_point_sec expiration_time)
69 {
70  expiration = expiration_time;
71 }
72 
73 void transaction::set_reference_block(const block_id_type& reference_block)
74 {
75  ref_block_num = fc::endian_reverse_u32(reference_block._hash[0]);
76  ref_block_prefix = reference_block._hash[1];
77 }
78 
79 void transaction::get_required_authorities(flat_set<account_name_type>& active,
80  flat_set<account_name_type>& owner,
81  flat_set<account_name_type>& posting,
82  std::vector<authority>& other) const
83 {
84  for (const auto& op : operations)
85  operation_get_required_authorities(op, active, owner, posting, other);
86 }
87 
88 void verify_authority(const std::vector<operation>& ops,
89  const flat_set<public_key_type>& sigs,
90  const authority_getter& get_active,
91  const authority_getter& get_owner,
92  const authority_getter& get_posting,
93  uint32_t max_recursion_depth,
94  bool allow_committe,
95  const flat_set<account_name_type>& active_aprovals,
96  const flat_set<account_name_type>& owner_approvals,
97  const flat_set<account_name_type>& posting_approvals)
98 {
99  try
100  {
101  flat_set<account_name_type> required_active;
102  flat_set<account_name_type> required_owner;
103  flat_set<account_name_type> required_posting;
104  std::vector<authority> other;
105 
106  for (const auto& op : ops)
107  operation_get_required_authorities(op, required_active, required_owner, required_posting, other);
108 
115  if (required_posting.size())
116  {
117  FC_ASSERT(required_active.size() == 0);
118  FC_ASSERT(required_owner.size() == 0);
119  FC_ASSERT(other.size() == 0);
120 
121  flat_set<public_key_type> avail;
122  sign_state s(sigs, get_posting, avail);
123  s.max_recursion = max_recursion_depth;
124  for (auto& id : posting_approvals)
125  s.approved_by.insert(id);
126  for (auto id : required_posting)
127  {
128  SCORUM_ASSERT(s.check_authority(id) || s.check_authority(get_active(id))
129  || s.check_authority(get_owner(id)),
130  tx_missing_posting_auth, "Missing Posting Authority ${id}",
131  ("id", id)("posting", get_posting(id))("active", get_active(id))("owner", get_owner(id)));
132  }
133  SCORUM_ASSERT(!s.remove_unused_signatures(), tx_irrelevant_sig, "Unnecessary signature(s) detected");
134  return;
135  }
136 
137  flat_set<public_key_type> avail;
138  sign_state s(sigs, get_active, avail);
139  s.max_recursion = max_recursion_depth;
140  for (auto& id : active_aprovals)
141  s.approved_by.insert(id);
142  for (auto& id : owner_approvals)
143  s.approved_by.insert(id);
144 
145  for (const auto& auth : other)
146  {
147  SCORUM_ASSERT(s.check_authority(auth), tx_missing_other_auth, "Missing Authority",
148  ("auth", auth)("sigs", sigs));
149  }
150 
151  // fetch all of the top level authorities
152  for (auto id : required_active)
153  {
154  SCORUM_ASSERT(s.check_authority(id) || s.check_authority(get_owner(id)), tx_missing_active_auth,
155  "Missing Active Authority ${id}", ("id", id)("auth", get_active(id))("owner", get_owner(id)));
156  }
157 
158  for (auto id : required_owner)
159  {
160  SCORUM_ASSERT(owner_approvals.find(id) != owner_approvals.end() || s.check_authority(get_owner(id)),
161  tx_missing_owner_auth, "Missing Owner Authority ${id}", ("id", id)("auth", get_owner(id)));
162  }
163 
164  SCORUM_ASSERT(!s.remove_unused_signatures(), tx_irrelevant_sig, "Unnecessary signature(s) detected");
165  }
166  FC_CAPTURE_AND_RETHROW((ops)(sigs))
167 }
168 
169 flat_set<public_key_type> signed_transaction::get_signature_keys(const chain_id_type& chain_id) const
170 {
171  try
172  {
173  auto d = sig_digest(chain_id);
174  flat_set<public_key_type> result;
175  for (const auto& sig : signatures)
176  {
177  SCORUM_ASSERT(result.insert(fc::ecc::public_key(sig, d)).second, tx_duplicate_sig,
178  "Duplicate Signature detected");
179  }
180  return result;
181  }
182  FC_CAPTURE_AND_RETHROW()
183 }
184 
185 std::set<public_key_type> signed_transaction::get_required_signatures(const chain_id_type& chain_id,
186  const flat_set<public_key_type>& available_keys,
187  const authority_getter& get_active,
188  const authority_getter& get_owner,
189  const authority_getter& get_posting,
190  uint32_t max_recursion_depth) const
191 {
192  flat_set<account_name_type> required_active;
193  flat_set<account_name_type> required_owner;
194  flat_set<account_name_type> required_posting;
195  std::vector<authority> other;
196  get_required_authorities(required_active, required_owner, required_posting, other);
197 
199  if (required_posting.size())
200  {
201  sign_state s(get_signature_keys(chain_id), get_posting, available_keys);
202  s.max_recursion = max_recursion_depth;
203 
204  FC_ASSERT(!required_owner.size());
205  FC_ASSERT(!required_active.size());
206  for (auto& posting : required_posting)
208 
210 
211  std::set<public_key_type> result;
212 
213  for (auto& provided_sig : s.provided_signatures)
214  if (available_keys.find(provided_sig.first) != available_keys.end())
215  result.insert(provided_sig.first);
216 
217  return result;
218  }
219 
220  sign_state s(get_signature_keys(chain_id), get_active, available_keys);
221  s.max_recursion = max_recursion_depth;
222 
223  for (const auto& auth : other)
224  s.check_authority(auth);
225  for (auto& owner : required_owner)
226  s.check_authority(get_owner(owner));
227  for (auto& active : required_active)
229 
231 
232  std::set<public_key_type> result;
233 
234  for (auto& provided_sig : s.provided_signatures)
235  if (available_keys.find(provided_sig.first) != available_keys.end())
236  result.insert(provided_sig.first);
237 
238  return result;
239 }
240 
241 std::set<public_key_type>
243  const flat_set<public_key_type>& available_keys,
244  const authority_getter& get_active,
245  const authority_getter& get_owner,
246  const authority_getter& get_posting,
247  uint32_t max_recursion) const
248 {
249  std::set<public_key_type> s
250  = get_required_signatures(chain_id, available_keys, get_active, get_owner, get_posting, max_recursion);
251  flat_set<public_key_type> result(s.begin(), s.end());
252 
253  for (const public_key_type& k : s)
254  {
255  result.erase(k);
256  try
257  {
258  scorum::protocol::verify_authority(operations, result, get_active, get_owner, get_posting, max_recursion);
259  continue; // element stays erased if verify_authority is ok
260  }
261  catch (const tx_missing_owner_auth& e)
262  {
263  }
264  catch (const tx_missing_active_auth& e)
265  {
266  }
267  catch (const tx_missing_posting_auth& e)
268  {
269  }
270  catch (const tx_missing_other_auth& e)
271  {
272  }
273  result.insert(k);
274  }
275  return std::set<public_key_type>(result.begin(), result.end());
276 }
277 
279  const authority_getter& get_active,
280  const authority_getter& get_owner,
281  const authority_getter& get_posting,
282  uint32_t max_recursion) const
283 {
284  try
285  {
286  scorum::protocol::verify_authority(operations, get_signature_keys(chain_id), get_active, get_owner, get_posting,
287  max_recursion);
288  }
289  FC_CAPTURE_AND_RETHROW((*this))
290 }
291 }
292 } // scorum::protocol
#define SCORUM_ASSERT(expr, exc_type, FORMAT,...)
Definition: exceptions.hpp:6
fc::ecc::private_key private_key_type
Definition: types.hpp:60
fc::ripemd160 transaction_id_type
Definition: types.hpp:65
fc::sha256 chain_id_type
Definition: types.hpp:61
void verify_authority(const std::vector< operation > &ops, const flat_set< public_key_type > &sigs, const authority_getter &get_active, const authority_getter &get_owner, const authority_getter &get_posting, uint32_t max_recursion=SCORUM_MAX_SIG_CHECK_DEPTH, bool allow_committe=false, const flat_set< account_name_type > &active_aprovals=flat_set< account_name_type >(), const flat_set< account_name_type > &owner_aprovals=flat_set< account_name_type >(), const flat_set< account_name_type > &posting_approvals=flat_set< account_name_type >())
Definition: transaction.cpp:88
fc::sha256 digest_type
Definition: types.hpp:66
fc::ripemd160 block_id_type
Definition: types.hpp:63
std::function< authority(const std::string &)> authority_getter
Definition: sign_state.hpp:9
void operation_validate(const proposal_operation &op)
fc::ecc::compact_signature signature_type
Definition: types.hpp:67
Definition: asset.cpp:15
bool check_authority(const std::string &id)
Definition: sign_state.cpp:20
flat_set< std::string > approved_by
Definition: sign_state.hpp:33
flat_map< public_key_type, bool > provided_signatures
Definition: sign_state.hpp:32
const signature_type & sign(const private_key_type &key, const chain_id_type &chain_id)
Definition: transaction.cpp:51
flat_set< public_key_type > get_signature_keys(const chain_id_type &chain_id) const
void verify_authority(const chain_id_type &chain_id, const authority_getter &get_active, const authority_getter &get_owner, const authority_getter &get_posting, uint32_t max_recursion=SCORUM_MAX_SIG_CHECK_DEPTH) const
std::set< public_key_type > get_required_signatures(const chain_id_type &chain_id, const flat_set< public_key_type > &available_keys, const authority_getter &get_active, const authority_getter &get_owner, const authority_getter &get_posting, uint32_t max_recursion=SCORUM_MAX_SIG_CHECK_DEPTH) const
std::set< public_key_type > minimize_required_signatures(const chain_id_type &chain_id, const flat_set< public_key_type > &available_keys, const authority_getter &get_active, const authority_getter &get_owner, const authority_getter &get_posting, uint32_t max_recursion=SCORUM_MAX_SIG_CHECK_DEPTH) const
std::vector< signature_type > signatures
Definition: transaction.hpp:83
transaction_id_type id() const
Definition: transaction.cpp:43
std::vector< operation > operations
Definition: transaction.hpp:18
fc::time_point_sec expiration
Definition: transaction.hpp:16
void get_required_authorities(flat_set< account_name_type > &active, flat_set< account_name_type > &owner, flat_set< account_name_type > &posting, std::vector< authority > &other) const
Definition: transaction.cpp:79
void set_reference_block(const block_id_type &reference_block)
Definition: transaction.cpp:73
digest_type sig_digest(const chain_id_type &chain_id) const
Definition: transaction.cpp:28
digest_type digest() const
Definition: transaction.cpp:21
void set_expiration(fc::time_point_sec expiration_time)
Definition: transaction.cpp:68