BitShares-Core  4.0.0
BitShares blockchain implementation and command-line interface software
custom_operations_plugin.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 oxarbitrage 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  */
24 
26 
27 #include <fc/crypto/hex.hpp>
28 #include <iostream>
30 
31 namespace graphene { namespace custom_operations {
32 
33 namespace detail
34 {
36 {
37  public:
39  : _self( _plugin )
40  { }
42 
43  void onBlock();
44 
46  {
47  return _self.database();
48  }
49 
51 
52  uint32_t _start_block = 45000000;
53 
54  private:
55 
56 };
57 
59 {
60  typedef void result_type;
61  account_id_type _fee_payer;
63 
64  custom_op_visitor(database& db, account_id_type fee_payer) { _db = &db; _fee_payer = fee_payer; };
65 
66  template<typename T>
67  void operator()(T &v) const {
68  v.validate();
69  custom_generic_evaluator evaluator(*_db, _fee_payer);
70  evaluator.do_apply(v);
71  }
72 };
73 
75 {
77  const vector<optional< operation_history_object > >& hist = db.get_applied_operations();
78  for( const optional< operation_history_object >& o_operation : hist )
79  {
80  if(!o_operation.valid() || !o_operation->op.is_type<custom_operation>())
81  continue;
82 
83  const custom_operation& custom_op = o_operation->op.get<custom_operation>();
84 
85  if(custom_op.data.size() == 0)
86  continue;
87 
88  try {
89  auto unpacked = fc::raw::unpack<custom_plugin_operation>(custom_op.data);
90  custom_op_visitor vtor(db, custom_op.fee_payer());
91  unpacked.visit(vtor);
92  }
93  catch (fc::exception& e) { // only api node will know if the unpack, validate or apply fails
94  wlog("Custom operations plugin serializing error: ${ex} in operation: ${op}",
95  ("ex", e.to_detail_string())("op", fc::json::to_string(custom_op)));
96  continue;
97  }
98  }
99 }
100 
102 {
103  return;
104 }
105 
106 } // end namespace detail
107 
109  my( new detail::custom_operations_plugin_impl(*this) )
110 {
111 }
112 
114 {
115 }
116 
118 {
119  return "custom_operations";
120 }
122 {
123  return "Stores arbitrary data for accounts by creating specially crafted custom operations.";
124 }
125 
127  boost::program_options::options_description& cli,
128  boost::program_options::options_description& cfg
129  )
130 {
131  cli.add_options()
132  ("custom-operations-start-block", boost::program_options::value<uint32_t>()->default_value(45000000),
133  "Start processing custom operations transactions with the plugin only after this block")
134  ;
135  cfg.add(cli);
136 
137 }
138 
139 void custom_operations_plugin::plugin_initialize(const boost::program_options::variables_map& options)
140 {
142 
143  if (options.count("custom-operations-start-block")) {
144  my->_start_block = options["custom-operations-start-block"].as<uint32_t>();
145  }
146 
147  database().applied_block.connect( [this]( const signed_block& b) {
148  if( b.block_num() >= my->_start_block )
149  my->onBlock();
150  } );
151 }
152 
154 {
155  ilog("custom_operations: plugin_startup() begin");
156 }
157 
158 } }
static string to_string(const variant &v, output_formatting format=stringify_large_ints_and_doubles, uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
Definition: json.cpp:638
vector< object_id_type > do_apply(const account_storage_map &o)
Wraps a derived index to intercept calls to create, modify, and remove so that callbacks may be fired...
Definition: index.hpp:309
fc::signal< void(const signed_block &)> applied_block
Definition: database.hpp:197
tracks the blockchain state in an extensible manner
Definition: database.hpp:70
Definition: api.cpp:56
Used to generate a useful error report when an exception is thrown.At each level in the stack where t...
Definition: exception.hpp:56
std::string to_detail_string(log_level ll=log_level::all) const
Definition: exception.cpp:183
virtual void plugin_initialize(const boost::program_options::variables_map &options) override
Perform early startup routines and register plugin indexes, callbacks, etc.
#define wlog(FORMAT,...)
Definition: logger.hpp:123
provides a generic way to add higher level protocols on top of witness consensusThere is no validatio...
Definition: custom.hpp:38
account_id_type fee_payer() const
Definition: custom.hpp:51
provides stack-based nullable value similar to boost::optional
Definition: optional.hpp:20
const vector< optional< operation_history_object > > & get_applied_operations() const
Definition: db_block.cpp:548
chain::database & database()
Definition: plugin.hpp:114
custom_op_visitor(database &db, account_id_type fee_payer)
#define ilog(FORMAT,...)
Definition: logger.hpp:117
virtual void plugin_startup() override
Begin normal runtime operations.
std::unique_ptr< detail::custom_operations_plugin_impl > my
virtual void plugin_set_program_options(boost::program_options::options_description &cli, boost::program_options::options_description &cfg) override
Fill in command line parameters used by the plugin.
uint32_t block_num() const
Definition: block.hpp:34