BitShares-Core  6.1.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 
28 
29 namespace graphene { namespace custom_operations {
30 
31 namespace detail
32 {
34 {
35  public:
37  : _self( _plugin )
38  { }
39 
40  void onBlock();
41 
43  {
44  return _self.database();
45  }
46 
48 
49  private:
51 
52  uint32_t _start_block = 45000000;
53 };
54 
56 {
57  typedef void result_type;
58  account_id_type _fee_payer;
60 
61  custom_op_visitor(database& db, account_id_type fee_payer) { _db = &db; _fee_payer = fee_payer; };
62 
63  template<typename T>
64  void operator()(T &v) const {
65  v.validate();
66  custom_generic_evaluator evaluator(*_db, _fee_payer);
67  evaluator.do_apply(v);
68  }
69 };
70 
72 {
74  const vector<optional< operation_history_object > >& hist = db.get_applied_operations();
75  for( const optional< operation_history_object >& o_operation : hist )
76  {
77  if(!o_operation.valid() || !o_operation->op.is_type<custom_operation>())
78  continue;
79 
80  const custom_operation& custom_op = o_operation->op.get<custom_operation>();
81 
82  if(custom_op.data.size() == 0)
83  continue;
84 
85  try {
86  auto unpacked = fc::raw::unpack<custom_plugin_operation>(custom_op.data);
87  custom_op_visitor vtor(db, custom_op.fee_payer());
88  unpacked.visit(vtor);
89  }
90  catch (fc::exception& e) { // only api node will know if the unpack, validate or apply fails
91  wlog("Custom operations plugin serializing error: ${ex} in operation: ${op}",
92  ("ex", e.to_detail_string())("op", fc::json::to_string(custom_op)));
93  continue;
94  }
95  }
96 }
97 
98 } // end namespace detail
99 
101  plugin(app),
102  my( std::make_unique<detail::custom_operations_plugin_impl>(*this) )
103 {
104  // Nothing to do
105 }
106 
108 
110 {
111  return "custom_operations";
112 }
114 {
115  return "Stores arbitrary data for accounts by creating specially crafted custom operations.";
116 }
117 
119  boost::program_options::options_description& cli,
120  boost::program_options::options_description& cfg
121  )
122 {
123  cli.add_options()
124  ("custom-operations-start-block", boost::program_options::value<uint32_t>()->default_value(45000000),
125  "Start processing custom operations transactions with the plugin only after this block")
126  ;
127  cfg.add(cli);
128 
129 }
130 
131 void custom_operations_plugin::plugin_initialize(const boost::program_options::variables_map& options)
132 {
134 
135  if (options.count("custom-operations-start-block") > 0) {
136  my->_start_block = options["custom-operations-start-block"].as<uint32_t>();
137  }
138 
139  // connect with group 0 to process before some special steps (e.g. snapshot or next_object_id)
140  database().applied_block.connect( 0, [this]( const signed_block& b) {
141  if( b.block_num() >= my->_start_block )
142  my->onBlock();
143  } );
144 }
145 
147 {
148  ilog("custom_operations: plugin_startup() begin");
149 }
150 
151 } }
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:650
account_id_type fee_payer() const
Definition: custom.hpp:51
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:312
std::string plugin_name() const override
Get the name of the plugin.
fc::signal< void(const signed_block &)> applied_block
Definition: database.hpp:606
tracks the blockchain state in an extensible manner
Definition: database.hpp:70
Definition: api.cpp:48
Used to generate a useful error report when an exception is thrown.At each level in the stack where t...
Definition: exception.hpp:56
void plugin_initialize(const boost::program_options::variables_map &options) override
Perform early startup routines and register plugin indexes, callbacks, etc.
std::string plugin_description() const override
Get the description of the plugin.
#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
const vector< optional< operation_history_object > > & get_applied_operations() const
Definition: db_block.cpp:553
provides stack-based nullable value similar to boost::optional
Definition: optional.hpp:20
uint32_t block_num() const
Definition: block.hpp:34
chain::database & database()
Definition: plugin.hpp:115
custom_op_visitor(database &db, account_id_type fee_payer)
#define ilog(FORMAT,...)
Definition: logger.hpp:117
void plugin_startup() override
Begin normal runtime operations.
std::string to_detail_string(log_level ll=log_level::all) const
Definition: exception.cpp:183
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.