wasm_interface.cpp 65.0 KB
Newer Older
B
Bart Wyatt 已提交
1 2
#include <eosio/chain/wasm_interface.hpp>
#include <eosio/chain/apply_context.hpp>
D
Daniel Larimer 已提交
3
#include <eosio/chain/controller.hpp>
4
#include <eosio/chain/producer_schedule.hpp>
5
#include <eosio/chain/exceptions.hpp>
D
Daniel Larimer 已提交
6
#include <boost/core/ignore_unused.hpp>
7
#include <boost/multiprecision/cpp_bin_float.hpp>
8
#include <eosio/chain/authorization_manager.hpp>
9
#include <eosio/chain/resource_limits.hpp>
10
#include <eosio/chain/wasm_interface_private.hpp>
11
#include <eosio/chain/wasm_eosio_validation.hpp>
12
#include <eosio/chain/wasm_eosio_injection.hpp>
D
Daniel Larimer 已提交
13 14
#include <eosio/chain/global_property_object.hpp>
#include <eosio/chain/account_object.hpp>
15
#include <fc/exception/exception.hpp>
16
#include <fc/crypto/sha256.hpp>
17
#include <fc/crypto/sha1.hpp>
18
#include <fc/io/raw.hpp>
19
#include <fc/utf8.hpp>
D
Daniel Larimer 已提交
20

21
#include <softfloat.hpp>
22 23
#include <boost/asio.hpp>
#include <boost/bind.hpp>
24
#include <fstream>
25

26
namespace eosio { namespace chain {
27 28
   using namespace webassembly;
   using namespace webassembly::common;
M
Matias Romeo 已提交
29

30
   wasm_interface::wasm_interface(vm_type vm) : my( new wasm_interface_impl(vm) ) {}
B
Bart Wyatt 已提交
31

32
   wasm_interface::~wasm_interface() {}
B
Bart Wyatt 已提交
33

34 35
   void wasm_interface::validate(const bytes& code) {
      Module module;
36 37 38 39 40 41
      try {
         Serialization::MemoryInputStream stream((U8*)code.data(), code.size());
         WASM::serialize(stream, module);
      } catch(Serialization::FatalSerializationException& e) {
         EOS_ASSERT(false, wasm_serialization_error, e.message.c_str());
      }
M
Matias Romeo 已提交
42

43
      wasm_validations::wasm_binary_validation validator(module);
44
      validator.validate();
M
Matias Romeo 已提交
45

46
      root_resolver resolver(true);
47
      LinkResult link_result = linkModule(module, resolver);
48

49 50 51
      //there are a couple opportunties for improvement here--
      //Easy: Cache the Module created here so it can be reused for instantiaion
      //Hard: Kick off instantiation in a separate thread at this location
52 53
   }

54
   void wasm_interface::apply( const digest_type& code_id, const shared_vector<char>& code, apply_context& context ) {
55
      my->get_instantiated_module(code_id, code)->apply(context);
56 57
   }

58
   wasm_instantiated_module_interface::~wasm_instantiated_module_interface() {}
59
   wasm_runtime_interface::~wasm_runtime_interface() {}
60

61
#if defined(assert)
62
   #undef assert
63
#endif
64

B
Bart Wyatt 已提交
65
class context_aware_api {
66
   public:
67 68
      context_aware_api(apply_context& ctx, bool context_free = false )
      :context(ctx)
D
Daniel Larimer 已提交
69 70 71 72 73
      {
         if( context.context_free )
            FC_ASSERT( context_free, "only context free api's can be used in this context" );
         context.used_context_free_api |= !context_free;
      }
74

B
Bart Wyatt 已提交
75
   protected:
76
      apply_context&             context;
B
Bart Wyatt 已提交
77

B
Bart Wyatt 已提交
78
};
79

D
Daniel Larimer 已提交
80 81
class context_free_api : public context_aware_api {
   public:
82 83
      context_free_api( apply_context& ctx )
      :context_aware_api(ctx, true) {
D
Daniel Larimer 已提交
84 85 86 87 88 89 90 91
         /* the context_free_data is not available during normal application because it is prunable */
         FC_ASSERT( context.context_free, "this API may only be called from context_free apply" );
      }

      int get_context_free_data( uint32_t index, array_ptr<char> buffer, size_t buffer_size )const {
         return context.get_context_free_data( index, buffer, buffer_size );
      }
};
92

D
Daniel Larimer 已提交
93 94
class privileged_api : public context_aware_api {
   public:
95 96
      privileged_api( apply_context& ctx )
      :context_aware_api(ctx)
97 98 99
      {
         FC_ASSERT( context.privileged, "${code} does not have permission to call this API", ("code",context.receiver) );
      }
100

101 102 103 104 105 106 107 108 109 110
      /**
       * This should return true if a feature is active and irreversible, false if not.
       *
       * Irreversiblity by fork-database is not consensus safe, therefore, this defines
       * irreversiblity only by block headers not by BFT short-cut.
       */
      int is_feature_active( int64_t feature_name ) {
         return false;
      }

D
Daniel Larimer 已提交
111 112 113 114 115
      /**
       *  This should schedule the feature to be activated once the
       *  block that includes this call is irreversible. It should
       *  fail if the feature is already pending.
       *
116
       *  Feature name should be base32 encoded name.
D
Daniel Larimer 已提交
117
       */
118
      void activate_feature( int64_t feature_name ) {
B
Bucky Kittinger 已提交
119
         FC_ASSERT( !"Unsupported Hardfork Detected" );
D
Daniel Larimer 已提交
120
      }
121

B
Bart Wyatt 已提交
122 123 124 125 126 127 128 129 130
      /**
       * update the resource limits associated with an account.  Note these new values will not take effect until the
       * next resource "tick" which is currently defined as a cycle boundary inside a block.
       *
       * @param account - the account whose limits are being modified
       * @param ram_bytes - the limit for ram bytes
       * @param net_weight - the weight for determining share of network capacity
       * @param cpu_weight - the weight for determining share of compute capacity
       */
131
      void set_resource_limits( account_name account, int64_t ram_bytes, int64_t net_weight, int64_t cpu_weight) {
132 133 134
         EOS_ASSERT(ram_bytes >= -1, wasm_execution_error, "invalid value for ram resource limit expected [-1,INT64_MAX]");
         EOS_ASSERT(net_weight >= -1, wasm_execution_error, "invalid value for net resource weight expected [-1,INT64_MAX]");
         EOS_ASSERT(cpu_weight >= -1, wasm_execution_error, "invalid value for cpu resource weight expected [-1,INT64_MAX]");
135
         context.mutable_controller.get_mutable_resource_limits_manager().set_account_limits(account, ram_bytes, net_weight, cpu_weight);
D
Daniel Larimer 已提交
136
      }
137

138
      void get_resource_limits( account_name account, int64_t& ram_bytes, int64_t& net_weight, int64_t& cpu_weight ) {
D
Daniel Larimer 已提交
139
         context.control.get_resource_limits_manager().get_account_limits( account, ram_bytes, net_weight, cpu_weight);
D
Daniel Larimer 已提交
140
      }
141

142
      bool set_active_producers( array_ptr<char> packed_producer_schedule, size_t datalen) {
143
         datastream<const char*> ds( packed_producer_schedule, datalen );
144 145
         vector<producer_key> producers;
         fc::raw::unpack(ds, producers);
146 147
         // check that producers are unique
         std::set<account_name> unique_producers;
148 149
         for (const auto& p: producers) {
            EOS_ASSERT( context.is_account(p.producer_name), wasm_execution_error, "producer schedule includes a nonexisting account" );
150
            EOS_ASSERT( p.block_signing_key.valid(), wasm_execution_error, "producer schedule includes an invalid key" );
151 152
            unique_producers.insert(p.producer_name);
         }
153 154
         EOS_ASSERT( producers.size() == unique_producers.size(), wasm_execution_error, "duplicate producer name in producer schedule" );
         return context.mutable_controller.set_proposed_producers( std::move(producers) );
D
Daniel Larimer 已提交
155
      }
156

157
      uint32_t get_blockchain_parameters_packed( array_ptr<char> packed_blockchain_parameters, size_t datalen) {
D
Daniel Larimer 已提交
158
         auto& gpo = context.control.get_global_properties();
159 160 161 162 163 164 165 166
         auto size = fc::raw::pack_size( gpo.configuration );
         if ( size <= datalen ) {
            datastream<char*> ds( packed_blockchain_parameters, datalen );
            fc::raw::pack(ds, gpo.configuration);
         }
         return size;
      }

167 168 169 170 171

      void set_blockchain_parameters_packed( array_ptr<char> packed_blockchain_parameters, size_t datalen) {
         datastream<const char*> ds( packed_blockchain_parameters, datalen );
         chain::chain_config cfg;
         fc::raw::unpack(ds, cfg);
D
Daniel Larimer 已提交
172
         context.db.modify( context.control.get_global_properties(),
173 174 175 176 177
            [&]( auto& gprops ) {
                 gprops.configuration = cfg;
         });
      }

178 179 180
      bool is_privileged( account_name n )const {
         return context.db.get<account_object, by_name>( n ).privileged;
      }
D
Daniel Larimer 已提交
181

182 183
      void set_privileged( account_name n, bool is_priv ) {
         const auto& a = context.db.get<account_object, by_name>( n );
D
Daniel Larimer 已提交
184
         context.db.modify( a, [&]( auto& ma ){
185 186
            ma.privileged = is_priv;
         });
D
Daniel Larimer 已提交
187
      }
188

D
Daniel Larimer 已提交
189
};
B
Brian Johnson 已提交
190

191 192
class checktime_api : public context_aware_api {
public:
193 194
   explicit checktime_api( apply_context& ctx )
   :context_aware_api(ctx,true){}
195

196 197
   void checktime(uint32_t instruction_count) {
      context.checktime(instruction_count);
B
Brian Johnson 已提交
198
   }
199
};
200

201 202 203 204 205
class softfloat_api : public context_aware_api {
   public:
      // TODO add traps on truncations for special cases (NaN or outside the range which rounds to an integer)
      using context_aware_api::context_aware_api;
      // float binops
206
      float _eosio_f32_add( float a, float b ) {
207 208 209
         float32_t ret = f32_add( to_softfloat32(a), to_softfloat32(b) );
         return *reinterpret_cast<float*>(&ret);
      }
210
      float _eosio_f32_sub( float a, float b ) {
211 212 213
         float32_t ret = f32_sub( to_softfloat32(a), to_softfloat32(b) );
         return *reinterpret_cast<float*>(&ret);
      }
214
      float _eosio_f32_div( float a, float b ) {
215 216 217
         float32_t ret = f32_div( to_softfloat32(a), to_softfloat32(b) );
         return *reinterpret_cast<float*>(&ret);
      }
218
      float _eosio_f32_mul( float a, float b ) {
219 220 221
         float32_t ret = f32_mul( to_softfloat32(a), to_softfloat32(b) );
         return *reinterpret_cast<float*>(&ret);
      }
222
      float _eosio_f32_min( float af, float bf ) {
223 224
         float32_t a = to_softfloat32(af);
         float32_t b = to_softfloat32(bf);
225
         if (is_nan(a)) {
226
            return af;
227
         }
228
         if (is_nan(b)) {
229
            return bf;
230
         }
231 232
         if ( sign_bit(a) != sign_bit(b) ) {
            return sign_bit(a) ? af : bf;
233
         }
234
         return f32_lt(a,b) ? af : bf;
235
      }
236
      float _eosio_f32_max( float af, float bf ) {
237 238
         float32_t a = to_softfloat32(af);
         float32_t b = to_softfloat32(bf);
239
         if (is_nan(a)) {
240
            return af;
241
         }
242 243
         if (is_nan(b)) {
            return bf;
244
         }
245 246
         if ( sign_bit(a) != sign_bit(b) ) {
            return sign_bit(a) ? bf : af;
247
         }
248
         return f32_lt( a, b ) ? bf : af;
249
      }
250
      float _eosio_f32_copysign( float af, float bf ) {
251 252
         float32_t a = to_softfloat32(af);
         float32_t b = to_softfloat32(bf);
253 254 255 256
         uint32_t sign_of_a = a.v >> 31;
         uint32_t sign_of_b = b.v >> 31;
         a.v &= ~(1 << 31);             // clear the sign bit
         a.v = a.v | (sign_of_b << 31); // add the sign of b
257
         return from_softfloat32(a);
258 259
      }
      // float unops
260
      float _eosio_f32_abs( float af ) {
261
         float32_t a = to_softfloat32(af);
262
         a.v &= ~(1 << 31);
263
         return from_softfloat32(a);
264
      }
265
      float _eosio_f32_neg( float af ) {
266
         float32_t a = to_softfloat32(af);
267
         uint32_t sign = a.v >> 31;
268
         a.v &= ~(1 << 31);
269
         a.v |= (!sign << 31);
270
         return from_softfloat32(a);
271
      }
272 273 274
      float _eosio_f32_sqrt( float a ) {
         float32_t ret = f32_sqrt( to_softfloat32(a) );
         return from_softfloat32(ret);
275 276
      }
      // ceil, floor, trunc and nearest are lifted from libc
277 278
      float _eosio_f32_ceil( float af ) {
         float32_t a = to_softfloat32(af);
279
         int e = (int)(a.v >> 23 & 0xFF) - 0X7F;
280 281
         uint32_t m;
         if (e >= 23)
282
            return af;
283
         if (e >= 0) {
284
            m = 0x007FFFFF >> e;
285
            if ((a.v & m) == 0)
286
               return af;
287 288 289 290 291 292 293 294 295
            if (a.v >> 31 == 0)
               a.v += m;
            a.v &= ~m;
         } else {
            if (a.v >> 31)
               a.v = 0x80000000; // return -0.0f
            else if (a.v << 1)
               a.v = 0x3F800000; // return 1.0f
         }
296

297
         return from_softfloat32(a);
298
      }
299 300
      float _eosio_f32_floor( float af ) {
         float32_t a = to_softfloat32(af);
301
         int e = (int)(a.v >> 23 & 0xFF) - 0X7F;
302 303
         uint32_t m;
         if (e >= 23)
304
            return af;
305
         if (e >= 0) {
306
            m = 0x007FFFFF >> e;
307
            if ((a.v & m) == 0)
308
               return af;
309 310 311 312 313 314 315
            if (a.v >> 31)
               a.v += m;
            a.v &= ~m;
         } else {
            if (a.v >> 31 == 0)
               a.v = 0;
            else if (a.v << 1)
316
               a.v = 0xBF800000; // return -1.0f
317
         }
318
         return from_softfloat32(a);
319
      }
320 321
      float _eosio_f32_trunc( float af ) {
         float32_t a = to_softfloat32(af);
322 323 324
         int e = (int)(a.v >> 23 & 0xff) - 0x7f + 9;
         uint32_t m;
         if (e >= 23 + 9)
325
            return af;
326 327 328 329
         if (e < 9)
            e = 1;
         m = -1U >> e;
         if ((a.v & m) == 0)
330
            return af;
331
         a.v &= ~m;
332
         return from_softfloat32(a);
333
      }
334 335
      float _eosio_f32_nearest( float af ) {
         float32_t a = to_softfloat32(af);
336 337 338 339
         int e = a.v>>23 & 0xff;
         int s = a.v>>31;
         float32_t y;
         if (e >= 0x7f+23)
340
            return af;
341
         if (s)
B
Bucky Kittinger 已提交
342
            y = f32_add( f32_sub( a, float32_t{inv_float_eps} ), float32_t{inv_float_eps} );
343
         else
B
Bucky Kittinger 已提交
344
            y = f32_sub( f32_add( a, float32_t{inv_float_eps} ), float32_t{inv_float_eps} );
345
         if (f32_eq( y, {0} ) )
346 347
            return s ? -0.0f : 0.0f;
         return from_softfloat32(y);
348
      }
349

350
      // float relops
351
      bool _eosio_f32_eq( float a, float b ) {  return f32_eq( to_softfloat32(a), to_softfloat32(b) ); }
352 353 354
      bool _eosio_f32_ne( float a, float b ) { return !f32_eq( to_softfloat32(a), to_softfloat32(b) ); }
      bool _eosio_f32_lt( float a, float b ) { return f32_lt( to_softfloat32(a), to_softfloat32(b) ); }
      bool _eosio_f32_le( float a, float b ) { return f32_le( to_softfloat32(a), to_softfloat32(b) ); }
355
      bool _eosio_f32_gt( float af, float bf ) {
356 357 358 359 360 361
         float32_t a = to_softfloat32(af);
         float32_t b = to_softfloat32(bf);
         if (is_nan(a))
            return false;
         if (is_nan(b))
            return false;
362
         return !f32_le( a, b );
363 364 365 366 367 368 369 370
      }
      bool _eosio_f32_ge( float af, float bf ) {
         float32_t a = to_softfloat32(af);
         float32_t b = to_softfloat32(bf);
         if (is_nan(a))
            return false;
         if (is_nan(b))
            return false;
371
         return !f32_lt( a, b );
372
      }
373 374

      // double binops
375 376 377
      double _eosio_f64_add( double a, double b ) {
         float64_t ret = f64_add( to_softfloat64(a), to_softfloat64(b) );
         return from_softfloat64(ret);
378
      }
379 380 381
      double _eosio_f64_sub( double a, double b ) {
         float64_t ret = f64_sub( to_softfloat64(a), to_softfloat64(b) );
         return from_softfloat64(ret);
382
      }
383 384 385
      double _eosio_f64_div( double a, double b ) {
         float64_t ret = f64_div( to_softfloat64(a), to_softfloat64(b) );
         return from_softfloat64(ret);
386
      }
387 388 389
      double _eosio_f64_mul( double a, double b ) {
         float64_t ret = f64_mul( to_softfloat64(a), to_softfloat64(b) );
         return from_softfloat64(ret);
390
      }
391
      double _eosio_f64_min( double af, double bf ) {
392 393 394 395 396 397 398 399 400
         float64_t a = to_softfloat64(af);
         float64_t b = to_softfloat64(bf);
         if (is_nan(a))
            return af;
         if (is_nan(b))
            return bf;
         if (sign_bit(a) != sign_bit(b))
            return sign_bit(a) ? af : bf;
         return f64_lt( a, b ) ? af : bf;
401 402
      }
      double _eosio_f64_max( double af, double bf ) {
403 404 405 406 407 408 409 410 411
         float64_t a = to_softfloat64(af);
         float64_t b = to_softfloat64(bf);
         if (is_nan(a))
            return af;
         if (is_nan(b))
            return bf;
         if (sign_bit(a) != sign_bit(b))
            return sign_bit(a) ? bf : af;
         return f64_lt( a, b ) ? bf : af;
412 413 414 415
      }
      double _eosio_f64_copysign( double af, double bf ) {
         float64_t a = to_softfloat64(af);
         float64_t b = to_softfloat64(bf);
416 417 418 419
         uint64_t sign_of_a = a.v >> 63;
         uint64_t sign_of_b = b.v >> 63;
         a.v &= ~(uint64_t(1) << 63);             // clear the sign bit
         a.v = a.v | (sign_of_b << 63); // add the sign of b
420
         return from_softfloat64(a);
421 422 423
      }

      // double unops
424
      double _eosio_f64_abs( double af ) {
425
         float64_t a = to_softfloat64(af);
426
         a.v &= ~(uint64_t(1) << 63);
427
         return from_softfloat64(a);
428
      }
429
      double _eosio_f64_neg( double af ) {
430
         float64_t a = to_softfloat64(af);
431
         uint64_t sign = a.v >> 63;
432
         a.v &= ~(uint64_t(1) << 63);
433
         a.v |= (uint64_t(!sign) << 63);
434
         return from_softfloat64(a);
435
      }
436
      double _eosio_f64_sqrt( double a ) {
437
         float64_t ret = f64_sqrt( to_softfloat64(a) );
438
         return from_softfloat64(ret);
439 440
      }
      // ceil, floor, trunc and nearest are lifted from libc
441
      double _eosio_f64_ceil( double af ) {
442
         float64_t a = to_softfloat64( af );
443
         float64_t ret;
444 445 446
         int e = a.v >> 52 & 0x7ff;
         float64_t y;
         if (e >= 0x3ff+52 || f64_eq( a, { 0 } ))
447
            return af;
448 449
         /* y = int(x) - x, where int(x) is an integer neighbor of x */
         if (a.v >> 63)
B
Bucky Kittinger 已提交
450
            y = f64_sub( f64_add( f64_sub( a, float64_t{inv_double_eps} ), float64_t{inv_double_eps} ), a );
451
         else
B
Bucky Kittinger 已提交
452
            y = f64_sub( f64_sub( f64_add( a, float64_t{inv_double_eps} ), float64_t{inv_double_eps} ), a );
453 454
         /* special case because of non-nearest rounding modes */
         if (e <= 0x3ff-1) {
455 456
            return a.v >> 63 ? -0.0 : 1.0; //float64_t{0x8000000000000000} : float64_t{0xBE99999A3F800000}; //either -0.0 or 1
         }
457 458
         if (f64_lt( y, to_softfloat64(0) )) {
            ret = f64_add( f64_add( a, y ), to_softfloat64(1) ); // 0xBE99999A3F800000 } ); // plus 1
459
            return from_softfloat64(ret);
460
         }
461
         ret = f64_add( a, y );
462
         return from_softfloat64(ret);
463
      }
464
      double _eosio_f64_floor( double af ) {
465
         float64_t a = to_softfloat64( af );
466
         float64_t ret;
467 468
         int e = a.v >> 52 & 0x7FF;
         float64_t y;
469 470
         double de = 1/DBL_EPSILON;
         if ( a.v == 0x8000000000000000) {
471
            return af;
472 473 474 475
         }
         if (e >= 0x3FF+52 || a.v == 0) {
            return af;
         }
476
         if (a.v >> 63)
B
Bucky Kittinger 已提交
477
            y = f64_sub( f64_add( f64_sub( a, float64_t{inv_double_eps} ), float64_t{inv_double_eps} ), a );
478
         else
B
Bucky Kittinger 已提交
479
            y = f64_sub( f64_sub( f64_add( a, float64_t{inv_double_eps} ), float64_t{inv_double_eps} ), a );
480
         if (e <= 0x3FF-1) {
481
            return a.v>>63 ? -1.0 : 0.0; //float64_t{0xBFF0000000000000} : float64_t{0}; // -1 or 0
482
         }
483
         if ( !f64_le( y, float64_t{0} ) ) {
484
            ret = f64_sub( f64_add(a,y), to_softfloat64(1.0));
485
            return from_softfloat64(ret);
486 487
         }
         ret = f64_add( a, y );
488
         return from_softfloat64(ret);
489
      }
490
      double _eosio_f64_trunc( double af ) {
491
         float64_t a = to_softfloat64( af );
492 493 494
         int e = (int)(a.v >> 52 & 0x7ff) - 0x3ff + 12;
         uint64_t m;
         if (e >= 52 + 12)
495
            return af;
496 497 498 499
         if (e < 12)
            e = 1;
         m = -1ULL >> e;
         if ((a.v & m) == 0)
500
            return af;
501
         a.v &= ~m;
502
         return from_softfloat64(a);
503 504
      }

505
      double _eosio_f64_nearest( double af ) {
506
         float64_t a = to_softfloat64( af );
507 508 509 510
         int e = (a.v >> 52 & 0x7FF);
         int s = a.v >> 63;
         float64_t y;
         if ( e >= 0x3FF+52 )
511
            return af;
512
         if ( s )
B
Bucky Kittinger 已提交
513
            y = f64_add( f64_sub( a, float64_t{inv_double_eps} ), float64_t{inv_double_eps} );
514
         else
B
Bucky Kittinger 已提交
515
            y = f64_sub( f64_add( a, float64_t{inv_double_eps} ), float64_t{inv_double_eps} );
516
         if ( f64_eq( y, float64_t{0} ) )
517
            return s ? -0.0 : 0.0;
518
         return from_softfloat64(y);
519 520 521
      }

      // double relops
522 523 524 525
      bool _eosio_f64_eq( double a, double b ) { return f64_eq( to_softfloat64(a), to_softfloat64(b) ); }
      bool _eosio_f64_ne( double a, double b ) { return !f64_eq( to_softfloat64(a), to_softfloat64(b) ); }
      bool _eosio_f64_lt( double a, double b ) { return f64_lt( to_softfloat64(a), to_softfloat64(b) ); }
      bool _eosio_f64_le( double a, double b ) { return f64_le( to_softfloat64(a), to_softfloat64(b) ); }
526
      bool _eosio_f64_gt( double af, double bf ) {
527 528 529 530 531 532
         float64_t a = to_softfloat64(af);
         float64_t b = to_softfloat64(bf);
         if (is_nan(a))
            return false;
         if (is_nan(b))
            return false;
533
         return !f64_le( a, b );
534 535 536 537 538 539 540 541
      }
      bool _eosio_f64_ge( double af, double bf ) {
         float64_t a = to_softfloat64(af);
         float64_t b = to_softfloat64(bf);
         if (is_nan(a))
            return false;
         if (is_nan(b))
            return false;
542
         return !f64_lt( a, b );
543 544 545
      }

      // float and double conversions
546 547
      double _eosio_f32_promote( float a ) {
         return from_softfloat64(f32_to_f64( to_softfloat32(a)) );
B
Bucky Kittinger 已提交
548
      }
549 550
      float _eosio_f64_demote( double a ) {
         return from_softfloat32(f64_to_f32( to_softfloat64(a)) );
B
Bucky Kittinger 已提交
551
      }
552
      int32_t _eosio_f32_trunc_i32s( float af ) {
B
Bucky Kittinger 已提交
553
         float32_t a = to_softfloat32(af);
554
         if (_eosio_f32_ge(af, 2147483648.0f) || _eosio_f32_lt(af, -2147483648.0f))
555 556
            FC_THROW_EXCEPTION( eosio::chain::wasm_execution_error, "Error, f32.convert_s/i32 overflow" );

B
Bucky Kittinger 已提交
557 558
         if (is_nan(a))
            FC_THROW_EXCEPTION( eosio::chain::wasm_execution_error, "Error, f32.convert_s/i32 unrepresentable");
559
         return f32_to_i32( to_softfloat32(_eosio_f32_trunc( af )), 0, false );
B
Bucky Kittinger 已提交
560
      }
561
      int32_t _eosio_f64_trunc_i32s( double af ) {
B
Bucky Kittinger 已提交
562
         float64_t a = to_softfloat64(af);
563
         if (_eosio_f64_ge(af, 2147483648.0) || _eosio_f64_lt(af, -2147483648.0))
B
Bucky Kittinger 已提交
564 565 566
            FC_THROW_EXCEPTION( eosio::chain::wasm_execution_error, "Error, f64.convert_s/i32 overflow");
         if (is_nan(a))
            FC_THROW_EXCEPTION( eosio::chain::wasm_execution_error, "Error, f64.convert_s/i32 unrepresentable");
567
         return f64_to_i32( to_softfloat64(_eosio_f64_trunc( af )), 0, false );
B
Bucky Kittinger 已提交
568
      }
569
      uint32_t _eosio_f32_trunc_i32u( float af ) {
B
Bucky Kittinger 已提交
570
         float32_t a = to_softfloat32(af);
571 572
         if (_eosio_f32_ge(af, 4294967296.0f) || _eosio_f32_le(af, -1.0f))
            FC_THROW_EXCEPTION( eosio::chain::wasm_execution_error, "Error, f32.convert_u/i32 overflow");
B
Bucky Kittinger 已提交
573
         if (is_nan(a))
574
            FC_THROW_EXCEPTION( eosio::chain::wasm_execution_error, "Error, f32.convert_u/i32 unrepresentable");
575
         return f32_to_ui32( to_softfloat32(_eosio_f32_trunc( af )), 0, false );
B
Bucky Kittinger 已提交
576
      }
577
      uint32_t _eosio_f64_trunc_i32u( double af ) {
B
Bucky Kittinger 已提交
578
         float64_t a = to_softfloat64(af);
579 580
         if (_eosio_f64_ge(af, 4294967296.0) || _eosio_f64_le(af, -1.0))
            FC_THROW_EXCEPTION( eosio::chain::wasm_execution_error, "Error, f64.convert_u/i32 overflow");
B
Bucky Kittinger 已提交
581
         if (is_nan(a))
582
            FC_THROW_EXCEPTION( eosio::chain::wasm_execution_error, "Error, f64.convert_u/i32 unrepresentable");
583
         return f64_to_ui32( to_softfloat64(_eosio_f64_trunc( af )), 0, false );
B
Bucky Kittinger 已提交
584
      }
585
      int64_t _eosio_f32_trunc_i64s( float af ) {
B
Bucky Kittinger 已提交
586
         float32_t a = to_softfloat32(af);
587
         if (_eosio_f32_ge(af, 9223372036854775808.0f) || _eosio_f32_lt(af, -9223372036854775808.0f))
588
            FC_THROW_EXCEPTION( eosio::chain::wasm_execution_error, "Error, f32.convert_s/i64 overflow");
B
Bucky Kittinger 已提交
589
         if (is_nan(a))
590
            FC_THROW_EXCEPTION( eosio::chain::wasm_execution_error, "Error, f32.convert_s/i64 unrepresentable");
591
         return f32_to_i64( to_softfloat32(_eosio_f32_trunc( af )), 0, false );
B
Bucky Kittinger 已提交
592
      }
593
      int64_t _eosio_f64_trunc_i64s( double af ) {
B
Bucky Kittinger 已提交
594
         float64_t a = to_softfloat64(af);
595
         if (_eosio_f64_ge(af, 9223372036854775808.0) || _eosio_f64_lt(af, -9223372036854775808.0))
596
            FC_THROW_EXCEPTION( eosio::chain::wasm_execution_error, "Error, f64.convert_s/i64 overflow");
B
Bucky Kittinger 已提交
597
         if (is_nan(a))
598
            FC_THROW_EXCEPTION( eosio::chain::wasm_execution_error, "Error, f64.convert_s/i64 unrepresentable");
599 600

         return f64_to_i64( to_softfloat64(_eosio_f64_trunc( af )), 0, false );
B
Bucky Kittinger 已提交
601
      }
602
      uint64_t _eosio_f32_trunc_i64u( float af ) {
B
Bucky Kittinger 已提交
603
         float32_t a = to_softfloat32(af);
604 605
         if (_eosio_f32_ge(af, 18446744073709551616.0f) || _eosio_f32_le(af, -1.0f))
            FC_THROW_EXCEPTION( eosio::chain::wasm_execution_error, "Error, f32.convert_u/i64 overflow");
B
Bucky Kittinger 已提交
606
         if (is_nan(a))
607
            FC_THROW_EXCEPTION( eosio::chain::wasm_execution_error, "Error, f32.convert_u/i64 unrepresentable");
608
         return f32_to_ui64( to_softfloat32(_eosio_f32_trunc( af )), 0, false );
B
Bucky Kittinger 已提交
609
      }
610
      uint64_t _eosio_f64_trunc_i64u( double af ) {
B
Bucky Kittinger 已提交
611
         float64_t a = to_softfloat64(af);
612 613
         if (_eosio_f64_ge(af, 18446744073709551616.0) || _eosio_f64_le(af, -1.0))
            FC_THROW_EXCEPTION( eosio::chain::wasm_execution_error, "Error, f64.convert_u/i64 overflow");
B
Bucky Kittinger 已提交
614
         if (is_nan(a))
615
            FC_THROW_EXCEPTION( eosio::chain::wasm_execution_error, "Error, f64.convert_u/i64 unrepresentable");
616
         return f64_to_ui64( to_softfloat64(_eosio_f64_trunc( af )), 0, false );
B
Bucky Kittinger 已提交
617
      }
618 619
      float _eosio_i32_to_f32( int32_t a )  {
         return from_softfloat32(i32_to_f32( a ));
B
Bucky Kittinger 已提交
620
      }
621 622
      float _eosio_i64_to_f32( int64_t a ) {
         return from_softfloat32(i64_to_f32( a ));
B
Bucky Kittinger 已提交
623
      }
624 625
      float _eosio_ui32_to_f32( uint32_t a ) {
         return from_softfloat32(ui32_to_f32( a ));
B
Bucky Kittinger 已提交
626
      }
627 628
      float _eosio_ui64_to_f32( uint64_t a ) {
         return from_softfloat32(ui64_to_f32( a ));
B
Bucky Kittinger 已提交
629
      }
630 631
      double _eosio_i32_to_f64( int32_t a ) {
         return from_softfloat64(i32_to_f64( a ));
B
Bucky Kittinger 已提交
632
      }
633 634
      double _eosio_i64_to_f64( int64_t a ) {
         return from_softfloat64(i64_to_f64( a ));
B
Bucky Kittinger 已提交
635
      }
636 637
      double _eosio_ui32_to_f64( uint32_t a ) {
         return from_softfloat64(ui32_to_f64( a ));
B
Bucky Kittinger 已提交
638 639
      }
      double _eosio_ui64_to_f64( uint64_t a ) {
640
         return from_softfloat64(ui64_to_f64( a ));
B
Bucky Kittinger 已提交
641
      }
642 643 644


   private:
645
      inline float32_t to_softfloat32( float f ) {
646 647 648 649
         return *reinterpret_cast<float32_t*>(&f);
      }
      inline float64_t to_softfloat64( double d ) {
         return *reinterpret_cast<float64_t*>(&d);
650
      }
651 652 653 654 655
      inline float from_softfloat32( float32_t f ) {
         return *reinterpret_cast<float*>(&f);
      }
      inline double from_softfloat64( float64_t d ) {
         return *reinterpret_cast<double*>(&d);
656
      }
657
      static constexpr uint32_t inv_float_eps = 0x4B000000;
B
Bucky Kittinger 已提交
658
      static constexpr uint64_t inv_double_eps = 0x4330000000000000;
659 660 661 662 663

      inline bool sign_bit( float32_t f ) { return f.v >> 31; }
      inline bool sign_bit( float64_t f ) { return f.v >> 63; }
      inline bool is_nan( float32_t f ) {
         return ((f.v & 0x7FFFFFFF) > 0x7F800000);
664
      }
665 666 667 668
      inline bool is_nan( float64_t f ) {
         return ((f.v & 0x7FFFFFFFFFFFFFFF) > 0x7FF0000000000000);
      }

669
};
670 671 672
class producer_api : public context_aware_api {
   public:
      using context_aware_api::context_aware_api;
673

674
      int get_active_producers(array_ptr<chain::account_name> producers, size_t datalen) {
675
         auto active_producers = context.get_active_producers();
676
         size_t len = active_producers.size();
677
         size_t cpy_len = std::min(datalen, len);
A
Anton Perkov 已提交
678
         memcpy(producers, active_producers.data(), cpy_len * sizeof(chain::account_name));
679
         return len;
680 681 682 683
      }
};

class crypto_api : public context_aware_api {
684
   public:
685 686
      explicit crypto_api( apply_context& ctx )
      :context_aware_api(ctx,true){}
687

688 689
      /**
       * This method can be optimized out during replay as it has
690
       * no possible side effects other than "passing".
691
       */
K
Kevin Heifner 已提交
692
      void assert_recover_key( const fc::sha256& digest,
693 694 695 696 697 698 699 700
                        array_ptr<char> sig, size_t siglen,
                        array_ptr<char> pub, size_t publen ) {
         fc::crypto::signature s;
         fc::crypto::public_key p;
         datastream<const char*> ds( sig, siglen );
         datastream<const char*> pubds( pub, publen );

         fc::raw::unpack(ds, s);
B
Bucky Kittinger 已提交
701
         fc::raw::unpack(pubds, p);
702 703 704 705 706

         auto check = fc::crypto::public_key( s, digest, false );
         FC_ASSERT( check == p, "Error expected key different than recovered key" );
      }

K
Kevin Heifner 已提交
707
      int recover_key( const fc::sha256& digest,
708 709 710 711 712 713 714 715 716 717 718
                        array_ptr<char> sig, size_t siglen,
                        array_ptr<char> pub, size_t publen ) {
         fc::crypto::signature s;
         datastream<const char*> ds( sig, siglen );
         datastream<char*> pubds( pub, publen );

         fc::raw::unpack(ds, s);
         fc::raw::pack( pubds, fc::crypto::public_key( s, digest, false ) );
         return pubds.tellp();
      }

719 720 721 722 723
      void assert_sha256(array_ptr<char> data, size_t datalen, const fc::sha256& hash_val) {
         auto result = fc::sha256::hash( data, datalen );
         FC_ASSERT( result == hash_val, "hash miss match" );
      }

B
Bucky Kittinger 已提交
724
      void assert_sha1(array_ptr<char> data, size_t datalen, const fc::sha1& hash_val) {
B
Bucky Kittinger 已提交
725 726 727 728
         auto result = fc::sha1::hash( data, datalen );
         FC_ASSERT( result == hash_val, "hash miss match" );
      }

B
Bucky Kittinger 已提交
729
      void assert_sha512(array_ptr<char> data, size_t datalen, const fc::sha512& hash_val) {
B
Bucky Kittinger 已提交
730 731 732 733
         auto result = fc::sha512::hash( data, datalen );
         FC_ASSERT( result == hash_val, "hash miss match" );
      }

B
Bucky Kittinger 已提交
734
      void assert_ripemd160(array_ptr<char> data, size_t datalen, const fc::ripemd160& hash_val) {
B
Bucky Kittinger 已提交
735 736 737 738 739
         auto result = fc::ripemd160::hash( data, datalen );
         FC_ASSERT( result == hash_val, "hash miss match" );
      }


740 741 742 743
      void sha1(array_ptr<char> data, size_t datalen, fc::sha1& hash_val) {
         hash_val = fc::sha1::hash( data, datalen );
      }

744 745 746
      void sha256(array_ptr<char> data, size_t datalen, fc::sha256& hash_val) {
         hash_val = fc::sha256::hash( data, datalen );
      }
747 748 749 750 751 752 753 754

      void sha512(array_ptr<char> data, size_t datalen, fc::sha512& hash_val) {
         hash_val = fc::sha512::hash( data, datalen );
      }

      void ripemd160(array_ptr<char> data, size_t datalen, fc::ripemd160& hash_val) {
         hash_val = fc::ripemd160::hash( data, datalen );
      }
755 756
};

M
Matias Romeo 已提交
757 758 759 760 761 762 763 764 765 766 767 768 769 770
class permission_api : public context_aware_api {
   public:
      using context_aware_api::context_aware_api;

      bool check_authorization( account_name account, permission_name permission, array_ptr<char> packed_pubkeys, size_t datalen) {

         vector<public_key_type> pub_keys;
         datastream<const char*> ds( packed_pubkeys, datalen );
         while(ds.remaining()) {
            public_key_type pub;
            fc::raw::unpack(ds, pub);
            pub_keys.emplace_back(pub);
         }

771
         return context.control.get_authorization_manager().check_authorization(
M
Matias Romeo 已提交
772 773 774 775 776 777 778
            account, permission,
            {pub_keys.begin(), pub_keys.end()},
            false
         );
      }
};

779 780 781 782 783 784 785 786 787
class string_api : public context_aware_api {
   public:
      using context_aware_api::context_aware_api;

      void assert_is_utf8(array_ptr<const char> str, size_t datalen, null_terminated_ptr msg) {
         const bool test = fc::is_utf8(std::string( str, datalen ));

         FC_ASSERT( test, "assertion failed: ${s}", ("s",msg.value) );
      }
B
Bart Wyatt 已提交
788 789 790 791
};

class system_api : public context_aware_api {
   public:
792 793
      explicit system_api( apply_context& ctx )
      :context_aware_api(ctx,true){}
B
Bart Wyatt 已提交
794

795 796
      void abort() {
         edump(("abort() called"));
797
         FC_ASSERT( false, "abort() called");
798 799
      }

800
      void eosio_assert(bool condition, null_terminated_ptr str) {
801 802 803 804 805
         if( !condition ) {
            std::string message( str );
            edump((message));
            FC_ASSERT( condition, "assertion failed: ${s}", ("s",message));
         }
B
Bart Wyatt 已提交
806
      }
807

808 809 810 811
      void eosio_exit(int32_t code) {
         throw wasm_exit{code};
      }

812
      fc::time_point_sec now() {
D
Daniel Larimer 已提交
813
         return context.control.head_block_time();
814
      }
B
Bart Wyatt 已提交
815 816 817 818
};

class action_api : public context_aware_api {
   public:
819 820
   action_api( apply_context& ctx )
      :context_aware_api(ctx,true){}
B
Bart Wyatt 已提交
821

822
      int read_action_data(array_ptr<char> memory, size_t size) {
823
         FC_ASSERT(size > 0);
824
         int minlen = std::min<size_t>(context.act.data.size(), size);
825 826 827 828
         memcpy((void *)memory, context.act.data.data(), minlen);
         return minlen;
      }

829
      int action_data_size() {
B
Bart Wyatt 已提交
830
         return context.act.data.size();
831 832
      }

833
      fc::time_point_sec publication_time() {
D
Daniel Larimer 已提交
834
         return context.published_time;
835 836
      }

837 838 839
      name current_receiver() {
         return context.receiver;
      }
840
};
B
Brian Johnson 已提交
841

B
Bart Wyatt 已提交
842 843
class console_api : public context_aware_api {
   public:
844 845
      console_api( apply_context& ctx )
      :context_aware_api(ctx,true){}
B
Bart Wyatt 已提交
846

847 848
      void prints(null_terminated_ptr str) {
         context.console_append<const char*>(str);
B
Bart Wyatt 已提交
849 850 851
      }

      void prints_l(array_ptr<const char> str, size_t str_len ) {
852
         context.console_append(string(str, str_len));
B
Bart Wyatt 已提交
853 854
      }

D
Daniel Larimer 已提交
855 856 857 858 859
      void printui(uint64_t val) {
         context.console_append(val);
      }

      void printi(int64_t val) {
860
         context.console_append(val);
B
Bart Wyatt 已提交
861 862 863 864
      }

      void printi128(const unsigned __int128& val) {
         fc::uint128_t v(val>>64, uint64_t(val) );
865
         context.console_append(fc::variant(v).get_string());
B
Bart Wyatt 已提交
866 867
      }

868 869
      void printdf( double val ) {
         context.console_append(val);
D
Daniel Larimer 已提交
870
      }
871

872 873
      void printff( float val ) {
         context.console_append(val);
B
Bart Wyatt 已提交
874 875 876
      }

      void printn(const name& value) {
877
         context.console_append(value.to_string());
B
Bart Wyatt 已提交
878 879 880
      }

      void printhex(array_ptr<const char> data, size_t data_len ) {
881
         context.console_append(fc::to_hex(data, data_len));
B
Bart Wyatt 已提交
882 883 884
      }
};

A
arhag 已提交
885
#define DB_API_METHOD_WRAPPERS_SIMPLE_SECONDARY(IDX, TYPE)\
886 887 888 889 890 891 892 893 894
      int db_##IDX##_store( uint64_t scope, uint64_t table, uint64_t payer, uint64_t id, const TYPE& secondary ) {\
         return context.IDX.store( scope, table, payer, id, secondary );\
      }\
      void db_##IDX##_update( int iterator, uint64_t payer, const TYPE& secondary ) {\
         return context.IDX.update( iterator, payer, secondary );\
      }\
      void db_##IDX##_remove( int iterator ) {\
         return context.IDX.remove( iterator );\
      }\
A
arhag 已提交
895
      int db_##IDX##_find_secondary( uint64_t code, uint64_t scope, uint64_t table, const TYPE& secondary, uint64_t& primary ) {\
896 897 898
         return context.IDX.find_secondary(code, scope, table, secondary, primary);\
      }\
      int db_##IDX##_find_primary( uint64_t code, uint64_t scope, uint64_t table, TYPE& secondary, uint64_t primary ) {\
A
arhag 已提交
899
         return context.IDX.find_primary(code, scope, table, secondary, primary);\
900 901 902 903 904 905 906
      }\
      int db_##IDX##_lowerbound( uint64_t code, uint64_t scope, uint64_t table,  TYPE& secondary, uint64_t& primary ) {\
         return context.IDX.lowerbound_secondary(code, scope, table, secondary, primary);\
      }\
      int db_##IDX##_upperbound( uint64_t code, uint64_t scope, uint64_t table,  TYPE& secondary, uint64_t& primary ) {\
         return context.IDX.upperbound_secondary(code, scope, table, secondary, primary);\
      }\
907 908 909
      int db_##IDX##_end( uint64_t code, uint64_t scope, uint64_t table ) {\
         return context.IDX.end_secondary(code, scope, table);\
      }\
910 911 912 913 914 915 916
      int db_##IDX##_next( int iterator, uint64_t& primary  ) {\
         return context.IDX.next_secondary(iterator, primary);\
      }\
      int db_##IDX##_previous( int iterator, uint64_t& primary ) {\
         return context.IDX.previous_secondary(iterator, primary);\
      }

A
arhag 已提交
917 918
#define DB_API_METHOD_WRAPPERS_ARRAY_SECONDARY(IDX, ARR_SIZE, ARR_ELEMENT_TYPE)\
      int db_##IDX##_store( uint64_t scope, uint64_t table, uint64_t payer, uint64_t id, array_ptr<const ARR_ELEMENT_TYPE> data, size_t data_len) {\
A
arhag 已提交
919 920 921 922 923
         FC_ASSERT( data_len == ARR_SIZE,\
                    "invalid size of secondary key array for " #IDX ": given ${given} bytes but expected ${expected} bytes",\
                    ("given",data_len)("expected",ARR_SIZE) );\
         return context.IDX.store(scope, table, payer, id, data.value);\
      }\
A
arhag 已提交
924
      void db_##IDX##_update( int iterator, uint64_t payer, array_ptr<const ARR_ELEMENT_TYPE> data, size_t data_len ) {\
A
arhag 已提交
925 926 927 928 929 930 931 932
         FC_ASSERT( data_len == ARR_SIZE,\
                    "invalid size of secondary key array for " #IDX ": given ${given} bytes but expected ${expected} bytes",\
                    ("given",data_len)("expected",ARR_SIZE) );\
         return context.IDX.update(iterator, payer, data.value);\
      }\
      void db_##IDX##_remove( int iterator ) {\
         return context.IDX.remove(iterator);\
      }\
A
arhag 已提交
933
      int db_##IDX##_find_secondary( uint64_t code, uint64_t scope, uint64_t table, array_ptr<const ARR_ELEMENT_TYPE> data, size_t data_len, uint64_t& primary ) {\
A
arhag 已提交
934 935 936 937 938
         FC_ASSERT( data_len == ARR_SIZE,\
                    "invalid size of secondary key array for " #IDX ": given ${given} bytes but expected ${expected} bytes",\
                    ("given",data_len)("expected",ARR_SIZE) );\
         return context.IDX.find_secondary(code, scope, table, data, primary);\
      }\
A
arhag 已提交
939
      int db_##IDX##_find_primary( uint64_t code, uint64_t scope, uint64_t table, array_ptr<ARR_ELEMENT_TYPE> data, size_t data_len, uint64_t primary ) {\
A
arhag 已提交
940 941 942 943 944
         FC_ASSERT( data_len == ARR_SIZE,\
                    "invalid size of secondary key array for " #IDX ": given ${given} bytes but expected ${expected} bytes",\
                    ("given",data_len)("expected",ARR_SIZE) );\
         return context.IDX.find_primary(code, scope, table, data.value, primary);\
      }\
A
arhag 已提交
945
      int db_##IDX##_lowerbound( uint64_t code, uint64_t scope, uint64_t table, array_ptr<ARR_ELEMENT_TYPE> data, size_t data_len, uint64_t& primary ) {\
A
arhag 已提交
946 947 948 949 950
         FC_ASSERT( data_len == ARR_SIZE,\
                    "invalid size of secondary key array for " #IDX ": given ${given} bytes but expected ${expected} bytes",\
                    ("given",data_len)("expected",ARR_SIZE) );\
         return context.IDX.lowerbound_secondary(code, scope, table, data.value, primary);\
      }\
A
arhag 已提交
951
      int db_##IDX##_upperbound( uint64_t code, uint64_t scope, uint64_t table, array_ptr<ARR_ELEMENT_TYPE> data, size_t data_len, uint64_t& primary ) {\
A
arhag 已提交
952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967
         FC_ASSERT( data_len == ARR_SIZE,\
                    "invalid size of secondary key array for " #IDX ": given ${given} bytes but expected ${expected} bytes",\
                    ("given",data_len)("expected",ARR_SIZE) );\
         return context.IDX.upperbound_secondary(code, scope, table, data.value, primary);\
      }\
      int db_##IDX##_end( uint64_t code, uint64_t scope, uint64_t table ) {\
         return context.IDX.end_secondary(code, scope, table);\
      }\
      int db_##IDX##_next( int iterator, uint64_t& primary  ) {\
         return context.IDX.next_secondary(iterator, primary);\
      }\
      int db_##IDX##_previous( int iterator, uint64_t& primary ) {\
         return context.IDX.previous_secondary(iterator, primary);\
      }


D
Daniel Larimer 已提交
968 969 970 971 972 973 974 975 976 977 978 979 980
class database_api : public context_aware_api {
   public:
      using context_aware_api::context_aware_api;

      int db_store_i64( uint64_t scope, uint64_t table, uint64_t payer, uint64_t id, array_ptr<const char> buffer, size_t buffer_size ) {
         return context.db_store_i64( scope, table, payer, id, buffer, buffer_size );
      }
      void db_update_i64( int itr, uint64_t payer, array_ptr<const char> buffer, size_t buffer_size ) {
         context.db_update_i64( itr, payer, buffer, buffer_size );
      }
      void db_remove_i64( int itr ) {
         context.db_remove_i64( itr );
      }
981 982 983
      int db_get_i64( int itr, array_ptr<char> buffer, size_t buffer_size ) {
         return context.db_get_i64( itr, buffer, buffer_size );
      }
984 985
      int db_next_i64( int itr, uint64_t& primary ) {
         return context.db_next_i64(itr, primary);
986
      }
987 988
      int db_previous_i64( int itr, uint64_t& primary ) {
         return context.db_previous_i64(itr, primary);
D
Daniel Larimer 已提交
989
      }
990 991
      int db_find_i64( uint64_t code, uint64_t scope, uint64_t table, uint64_t id ) {
         return context.db_find_i64( code, scope, table, id );
D
Daniel Larimer 已提交
992
      }
993 994
      int db_lowerbound_i64( uint64_t code, uint64_t scope, uint64_t table, uint64_t id ) {
         return context.db_lowerbound_i64( code, scope, table, id );
D
Daniel Larimer 已提交
995
      }
996
      int db_upperbound_i64( uint64_t code, uint64_t scope, uint64_t table, uint64_t id ) {
A
arhag 已提交
997
         return context.db_upperbound_i64( code, scope, table, id );
D
Daniel Larimer 已提交
998
      }
999 1000 1001
      int db_end_i64( uint64_t code, uint64_t scope, uint64_t table ) {
         return context.db_end_i64( code, scope, table );
      }
1002

A
arhag 已提交
1003 1004
      DB_API_METHOD_WRAPPERS_SIMPLE_SECONDARY(idx64,  uint64_t)
      DB_API_METHOD_WRAPPERS_SIMPLE_SECONDARY(idx128, uint128_t)
A
arhag 已提交
1005
      DB_API_METHOD_WRAPPERS_ARRAY_SECONDARY(idx256, 2, uint128_t)
A
arhag 已提交
1006
      DB_API_METHOD_WRAPPERS_SIMPLE_SECONDARY(idx_double, uint64_t)
D
Daniel Larimer 已提交
1007 1008
};

1009
class memory_api : public context_aware_api {
1010
   public:
1011 1012
      memory_api( apply_context& ctx )
      :context_aware_api(ctx,true){}
A
arhag 已提交
1013

1014 1015 1016 1017
      char* memcpy( array_ptr<char> dest, array_ptr<const char> src, size_t length) {
         return (char *)::memcpy(dest, src, length);
      }

1018 1019 1020 1021
      char* memmove( array_ptr<char> dest, array_ptr<const char> src, size_t length) {
         return (char *)::memmove(dest, src, length);
      }

1022 1023 1024 1025
      int memcmp( array_ptr<const char> dest, array_ptr<const char> src, size_t length) {
         return ::memcmp(dest, src, length);
      }

B
Bucky Kittinger 已提交
1026
      char* memset( array_ptr<char> dest, int value, size_t length ) {
B
Bucky Kittinger 已提交
1027
         return (char *)::memset( dest, value, length );
B
Bucky Kittinger 已提交
1028
      }
1029 1030
};

1031 1032 1033 1034
class transaction_api : public context_aware_api {
   public:
      using context_aware_api::context_aware_api;

D
Daniel Larimer 已提交
1035 1036 1037 1038 1039 1040 1041 1042 1043
      void send_inline( array_ptr<char> data, size_t data_len ) {
         // TODO: use global properties object for dynamic configuration of this default_max_gen_trx_size
         FC_ASSERT( data_len < config::default_max_inline_action_size, "inline action too big" );

         action act;
         fc::raw::unpack<action>(data, data_len, act);
         context.execute_inline(std::move(act));
      }

1044 1045 1046 1047 1048 1049 1050 1051 1052
      void send_context_free_inline( array_ptr<char> data, size_t data_len ) {
         // TODO: use global properties object for dynamic configuration of this default_max_gen_trx_size
         FC_ASSERT( data_len < config::default_max_inline_action_size, "inline action too big" );

         action act;
         fc::raw::unpack<action>(data, data_len, act);
         context.execute_context_free_inline(std::move(act));
      }

1053
      void send_deferred( const uint128_t& sender_id, account_name payer, array_ptr<char> data, size_t data_len ) {
D
Daniel Larimer 已提交
1054 1055 1056 1057
         try {
            deferred_transaction dtrx;
            fc::raw::unpack<transaction>(data, data_len, dtrx);
            dtrx.sender = context.receiver;
1058
            dtrx.sender_id = sender_id;
D
Daniel Larimer 已提交
1059
            dtrx.execute_after = time_point_sec( (context.control.head_block_time() + fc::seconds(dtrx.delay_sec)) + fc::microseconds(999'999) ); // rounds up to nearest second
1060
            dtrx.payer = payer;
1061
            context.schedule_deferred_transaction(std::move(dtrx));
D
Daniel Larimer 已提交
1062 1063
         } FC_CAPTURE_AND_RETHROW((fc::to_hex(data, data_len)));
      }
A
Anton Perkov 已提交
1064

1065 1066
      void cancel_deferred( const unsigned __int128& val ) {
         fc::uint128_t sender_id(val>>64, uint64_t(val) );
1067
         context.cancel_deferred_transaction( (unsigned __int128)sender_id );
A
Anton Perkov 已提交
1068
      }
D
Daniel Larimer 已提交
1069 1070 1071 1072 1073
};


class context_free_transaction_api : public context_aware_api {
   public:
1074 1075
      context_free_transaction_api( apply_context& ctx )
      :context_aware_api(ctx,true){}
D
Daniel Larimer 已提交
1076

1077 1078 1079 1080 1081 1082 1083 1084 1085 1086
      int read_transaction( array_ptr<char> data, size_t data_len ) {
         bytes trx = context.get_packed_transaction();
         if (data_len >= trx.size()) {
            memcpy(data, trx.data(), trx.size());
         }
         return trx.size();
      }

      int transaction_size() {
         return context.get_packed_transaction().size();
1087 1088 1089
      }

      int expiration() {
D
Daniel Larimer 已提交
1090
        return context.trx.expiration.sec_since_epoch();
1091 1092 1093
      }

      int tapos_block_num() {
D
Daniel Larimer 已提交
1094
        return context.trx.ref_block_num;
1095
      }
1096
      int tapos_block_prefix() {
D
Daniel Larimer 已提交
1097
        return context.trx.ref_block_prefix;
1098 1099
      }

D
Daniel Larimer 已提交
1100 1101
      int get_action( uint32_t type, uint32_t index, array_ptr<char> buffer, size_t buffer_size )const {
         return context.get_action( type, index, buffer, buffer_size );
1102 1103
      }

1104 1105 1106 1107
      void check_auth( array_ptr<char> trx_data, size_t trx_size, array_ptr<char> perm_data, size_t perm_size ) {
         transaction trx = fc::raw::unpack<transaction>( trx_data, trx_size );
         vector<permission_level> perm = fc::raw::unpack<vector<permission_level>>( perm_data, perm_size );
         return context.check_auth( trx, perm );
1108
      }
1109 1110
};

1111 1112 1113
class compiler_builtins : public context_aware_api {
   public:
      using context_aware_api::context_aware_api;
1114
      void __ashlti3(__int128& ret, uint64_t low, uint64_t high, uint32_t shift) {
1115 1116 1117
         fc::uint128_t i(high, low);
         i <<= shift;
         ret = (unsigned __int128)i;
1118 1119
      }

1120
      void __ashrti3(__int128& ret, uint64_t low, uint64_t high, uint32_t shift) {
B
oops  
Bucky Kittinger 已提交
1121 1122 1123 1124 1125
         // retain the signedness
         ret = high;
         ret <<= 64;
         ret |= low;
         ret >>= shift;
1126
      }
1127

1128 1129 1130 1131 1132
      void __lshlti3(__int128& ret, uint64_t low, uint64_t high, uint32_t shift) {
         fc::uint128_t i(high, low);
         i <<= shift;
         ret = (unsigned __int128)i;
      }
1133

1134 1135 1136 1137 1138
      void __lshrti3(__int128& ret, uint64_t low, uint64_t high, uint32_t shift) {
         fc::uint128_t i(high, low);
         i >>= shift;
         ret = (unsigned __int128)i;
      }
A
arhag 已提交
1139

1140
      void __divti3(__int128& ret, uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb) {
B
oops  
Bucky Kittinger 已提交
1141 1142
         __int128 lhs = ha;
         __int128 rhs = hb;
A
arhag 已提交
1143

B
oops  
Bucky Kittinger 已提交
1144 1145
         lhs <<= 64;
         lhs |=  la;
1146

B
oops  
Bucky Kittinger 已提交
1147 1148
         rhs <<= 64;
         rhs |=  lb;
1149

A
arhag 已提交
1150
         FC_ASSERT(rhs != 0, "divide by zero");
1151

A
arhag 已提交
1152
         lhs /= rhs;
1153

B
oops  
Bucky Kittinger 已提交
1154
         ret = lhs;
A
arhag 已提交
1155
      }
1156

B
oops  
Bucky Kittinger 已提交
1157 1158 1159
      void __udivti3(unsigned __int128& ret, uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb) {
         unsigned __int128 lhs = ha;
         unsigned __int128 rhs = hb;
A
arhag 已提交
1160

B
oops  
Bucky Kittinger 已提交
1161 1162 1163 1164 1165
         lhs <<= 64;
         lhs |=  la;

         rhs <<= 64;
         rhs |=  lb;
1166

A
arhag 已提交
1167
         FC_ASSERT(rhs != 0, "divide by zero");
1168

A
arhag 已提交
1169
         lhs /= rhs;
B
oops  
Bucky Kittinger 已提交
1170 1171 1172 1173 1174 1175
         ret = lhs;
      }

      void __multi3(__int128& ret, uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb) {
         __int128 lhs = ha;
         __int128 rhs = hb;
1176

B
oops  
Bucky Kittinger 已提交
1177 1178
         lhs <<= 64;
         lhs |=  la;
1179

B
oops  
Bucky Kittinger 已提交
1180 1181
         rhs <<= 64;
         rhs |=  lb;
1182

A
arhag 已提交
1183
         lhs *= rhs;
B
oops  
Bucky Kittinger 已提交
1184
         ret = lhs;
A
arhag 已提交
1185
      }
1186 1187

      void __modti3(__int128& ret, uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb) {
B
oops  
Bucky Kittinger 已提交
1188 1189 1190 1191 1192
         __int128 lhs = ha;
         __int128 rhs = hb;

         lhs <<= 64;
         lhs |=  la;
A
arhag 已提交
1193

B
oops  
Bucky Kittinger 已提交
1194 1195
         rhs <<= 64;
         rhs |=  lb;
A
arhag 已提交
1196

B
oops  
Bucky Kittinger 已提交
1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208
         FC_ASSERT(rhs != 0, "divide by zero");

         lhs %= rhs;
         ret = lhs;
      }

      void __umodti3(unsigned __int128& ret, uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb) {
         unsigned __int128 lhs = ha;
         unsigned __int128 rhs = hb;

         lhs <<= 64;
         lhs |=  la;
A
arhag 已提交
1209

B
oops  
Bucky Kittinger 已提交
1210 1211
         rhs <<= 64;
         rhs |=  lb;
A
arhag 已提交
1212

B
oops  
Bucky Kittinger 已提交
1213
         FC_ASSERT(rhs != 0, "divide by zero");
1214

B
oops  
Bucky Kittinger 已提交
1215 1216
         lhs %= rhs;
         ret = lhs;
1217
      }
1218 1219

      void __addtf3( float128_t& ret, uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
1220 1221
         float128_t a = {{ la, ha }};
         float128_t b = {{ lb, hb }};
1222
         ret = f128_add( a, b );
1223
      }
1224
      void __subtf3( float128_t& ret, uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
1225 1226
         float128_t a = {{ la, ha }};
         float128_t b = {{ lb, hb }};
1227
         ret = f128_sub( a, b );
1228
      }
1229
      void __multf3( float128_t& ret, uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
1230 1231
         float128_t a = {{ la, ha }};
         float128_t b = {{ lb, hb }};
1232
         ret = f128_mul( a, b );
1233
      }
1234
      void __divtf3( float128_t& ret, uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
1235 1236
         float128_t a = {{ la, ha }};
         float128_t b = {{ lb, hb }};
1237
         ret = f128_div( a, b );
1238
      }
1239
      int __eqtf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
1240 1241
         float128_t a = {{ la, ha }};
         float128_t b = {{ la, ha }};
1242
         return f128_eq( a, b );
1243
      }
1244
      int __netf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
1245 1246
         float128_t a = {{ la, ha }};
         float128_t b = {{ la, ha }};
1247
         return !f128_eq( a, b );
1248
      }
1249
      int __getf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
1250 1251
         float128_t a = {{ la, ha }};
         float128_t b = {{ la, ha }};
1252
         return !f128_lt( a, b );
1253
      }
1254
      int __gttf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
1255 1256
         float128_t a = {{ la, ha }};
         float128_t b = {{ la, ha }};
1257
         return !f128_lt( a, b ) && !f128_eq( a, b );
1258
      }
1259
      int __letf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
1260 1261
         float128_t a = {{ la, ha }};
         float128_t b = {{ la, ha }};
1262
         return f128_le( a, b );
1263
      }
1264
      int __lttf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
1265 1266
         float128_t a = {{ la, ha }};
         float128_t b = {{ la, ha }};
1267
         return f128_lt( a, b );
1268
      }
1269
      int __cmptf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
1270 1271 1272 1273 1274 1275 1276 1277
         float128_t a = {{ la, ha }};
         float128_t b = {{ la, ha }};
         if ( f128_lt( a, b ) )
            return -1;
         if ( f128_eq( a, b ) )
            return 0;
         return 1;
      }
1278
      int __unordtf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
1279 1280 1281 1282 1283 1284
         float128_t a = {{ la, ha }};
         float128_t b = {{ la, ha }};
         if ( f128_isSignalingNaN( a ) || f128_isSignalingNaN( b ) )
            return 1;
         return 0;
      }
1285
      double __floatsidf( int32_t i ) {
D
Daniel Larimer 已提交
1286
         edump((i)( "warning returning float64") );
1287
         float64_t ret = i32_to_f64(i);
1288
         return *reinterpret_cast<double*>(&ret);
D
Daniel Larimer 已提交
1289 1290 1291 1292 1293 1294 1295
      }
      void __floatsitf( float128_t& ret, int32_t i ) {
         ret = i32_to_f128(i); /// TODO: should be 128
      }
      void __floatunsitf( float128_t& ret, uint32_t i ) {
         ret = ui32_to_f128(i); /// TODO: should be 128
      }
1296
      void __extendsftf2( float128_t& ret, uint32_t f ) {
1297
         float32_t in = { f };
1298
         ret = f32_to_f128( in );
1299
      }
1300
      void __extenddftf2( float128_t& ret, double in ) {
D
Daniel Larimer 已提交
1301
         edump(("warning in flaot64..." ));
1302
         ret = f64_to_f128( float64_t{*(uint64_t*)&in} );
1303
      }
1304
      int64_t __fixtfdi( uint64_t l, uint64_t h ) {
1305
         float128_t f = {{ l, h }};
1306 1307 1308
         return f128_to_i64( f, 0, false );
      }
      int32_t __fixtfsi( uint64_t l, uint64_t h ) {
1309
         float128_t f = {{ l, h }};
1310 1311 1312
         return f128_to_i32( f, 0, false );
      }
      uint64_t __fixunstfdi( uint64_t l, uint64_t h ) {
1313
         float128_t f = {{ l, h }};
1314 1315 1316
         return f128_to_ui64( f, 0, false );
      }
      uint32_t __fixunstfsi( uint64_t l, uint64_t h ) {
1317
         float128_t f = {{ l, h }};
1318 1319 1320
         return f128_to_ui32( f, 0, false );
      }
      uint64_t __trunctfdf2( uint64_t l, uint64_t h ) {
1321
         float128_t f = {{ l, h }};
1322 1323 1324
         return f128_to_f64( f ).v;
      }
      uint32_t __trunctfsf2( uint64_t l, uint64_t h ) {
1325
         float128_t f = {{ l, h }};
1326 1327
         return f128_to_f32( f ).v;
      }
1328

B
Bucky Kittinger 已提交
1329
      static constexpr uint32_t SHIFT_WIDTH = (sizeof(uint64_t)*8)-1;
1330 1331 1332 1333
};

class math_api : public context_aware_api {
   public:
1334 1335
      math_api( apply_context& ctx )
      :context_aware_api(ctx,true){}
1336 1337 1338 1339 1340

      void diveq_i128(unsigned __int128* self, const unsigned __int128* other) {
         fc::uint128_t s(*self);
         const fc::uint128_t o(*other);
         FC_ASSERT( o != 0, "divide by zero" );
A
arhag 已提交
1341

1342 1343
         s = s/o;
         *self = (unsigned __int128)s;
1344 1345
      }

1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
      void multeq_i128(unsigned __int128* self, const unsigned __int128* other) {
         fc::uint128_t s(*self);
         const fc::uint128_t o(*other);
         s *= o;
         *self = (unsigned __int128)s;
      }

      uint64_t double_add(uint64_t a, uint64_t b) {
         using DOUBLE = boost::multiprecision::cpp_bin_float_50;
         DOUBLE c = DOUBLE(*reinterpret_cast<double *>(&a))
                  + DOUBLE(*reinterpret_cast<double *>(&b));
         double res = c.convert_to<double>();
         return *reinterpret_cast<uint64_t *>(&res);
      }

      uint64_t double_mult(uint64_t a, uint64_t b) {
         using DOUBLE = boost::multiprecision::cpp_bin_float_50;
         DOUBLE c = DOUBLE(*reinterpret_cast<double *>(&a))
                  * DOUBLE(*reinterpret_cast<double *>(&b));
         double res = c.convert_to<double>();
         return *reinterpret_cast<uint64_t *>(&res);
      }

      uint64_t double_div(uint64_t a, uint64_t b) {
         using DOUBLE = boost::multiprecision::cpp_bin_float_50;
         DOUBLE divisor = DOUBLE(*reinterpret_cast<double *>(&b));
         FC_ASSERT(divisor != 0, "divide by zero");
         DOUBLE c = DOUBLE(*reinterpret_cast<double *>(&a)) / divisor;
         double res = c.convert_to<double>();
         return *reinterpret_cast<uint64_t *>(&res);
      }

      uint32_t double_eq(uint64_t a, uint64_t b) {
         using DOUBLE = boost::multiprecision::cpp_bin_float_50;
         return DOUBLE(*reinterpret_cast<double *>(&a)) == DOUBLE(*reinterpret_cast<double *>(&b));
      }

      uint32_t double_lt(uint64_t a, uint64_t b) {
         using DOUBLE = boost::multiprecision::cpp_bin_float_50;
         return DOUBLE(*reinterpret_cast<double *>(&a)) < DOUBLE(*reinterpret_cast<double *>(&b));
      }

      uint32_t double_gt(uint64_t a, uint64_t b) {
         using DOUBLE = boost::multiprecision::cpp_bin_float_50;
         return DOUBLE(*reinterpret_cast<double *>(&a)) > DOUBLE(*reinterpret_cast<double *>(&b));
      }

      uint64_t double_to_i64(uint64_t n) {
         using DOUBLE = boost::multiprecision::cpp_bin_float_50;
B
Bucky Kittinger 已提交
1395
         return DOUBLE(*reinterpret_cast<double *>(&n)).convert_to<int64_t>();
1396 1397
      }

B
Bucky Kittinger 已提交
1398
      uint64_t i64_to_double(int64_t n) {
1399 1400 1401 1402
         using DOUBLE = boost::multiprecision::cpp_bin_float_50;
         double res = DOUBLE(n).convert_to<double>();
         return *reinterpret_cast<uint64_t *>(&res);
      }
1403 1404
};

1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416
REGISTER_INTRINSICS(math_api,
   (diveq_i128,    void(int, int)            )
   (multeq_i128,   void(int, int)            )
   (double_add,    int64_t(int64_t, int64_t) )
   (double_mult,   int64_t(int64_t, int64_t) )
   (double_div,    int64_t(int64_t, int64_t) )
   (double_eq,     int32_t(int64_t, int64_t) )
   (double_lt,     int32_t(int64_t, int64_t) )
   (double_gt,     int32_t(int64_t, int64_t) )
   (double_to_i64, int64_t(int64_t)          )
   (i64_to_double, int64_t(int64_t)          )
);
B
Bucky Kittinger 已提交
1417

1418
REGISTER_INTRINSICS(compiler_builtins,
B
Bucky Kittinger 已提交
1419 1420 1421 1422 1423 1424 1425 1426 1427
   (__ashlti3,     void(int, int64_t, int64_t, int)               )
   (__ashrti3,     void(int, int64_t, int64_t, int)               )
   (__lshlti3,     void(int, int64_t, int64_t, int)               )
   (__lshrti3,     void(int, int64_t, int64_t, int)               )
   (__divti3,      void(int, int64_t, int64_t, int64_t, int64_t)  )
   (__udivti3,     void(int, int64_t, int64_t, int64_t, int64_t)  )
   (__modti3,      void(int, int64_t, int64_t, int64_t, int64_t)  )
   (__umodti3,     void(int, int64_t, int64_t, int64_t, int64_t)  )
   (__multi3,      void(int, int64_t, int64_t, int64_t, int64_t)  )
1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438
   (__addtf3,      void(int, int64_t, int64_t, int64_t, int64_t)  )
   (__subtf3,      void(int, int64_t, int64_t, int64_t, int64_t)  )
   (__multf3,      void(int, int64_t, int64_t, int64_t, int64_t)  )
   (__divtf3,      void(int, int64_t, int64_t, int64_t, int64_t)  )
   (__eqtf2,       int(int64_t, int64_t, int64_t, int64_t)        )
   (__netf2,       int(int64_t, int64_t, int64_t, int64_t)        )
   (__getf2,       int(int64_t, int64_t, int64_t, int64_t)        )
   (__gttf2,       int(int64_t, int64_t, int64_t, int64_t)        )
   (__lttf2,       int(int64_t, int64_t, int64_t, int64_t)        )
   (__cmptf2,      int(int64_t, int64_t, int64_t, int64_t)        )
   (__unordtf2,    int(int64_t, int64_t, int64_t, int64_t)        )
D
Daniel Larimer 已提交
1439 1440
   (__floatsitf,   void (int, int)                                )
   (__floatunsitf, void (int, int)                                )
1441
   (__floatsidf,   double(int)                                    )
1442
   (__extendsftf2, void(int, int)                                 )
1443
   (__extenddftf2, void(int, double)                              )
1444 1445 1446 1447 1448 1449
   (__fixtfdi,     int64_t(int64_t, int64_t)                      )
   (__fixtfsi,     int(int64_t, int64_t)                          )
   (__fixunstfdi,  int64_t(int64_t, int64_t)                      )
   (__fixunstfsi,  int(int64_t, int64_t)                          )
   (__trunctfdf2,  int64_t(int64_t, int64_t)                      )
   (__trunctfsf2,  int(int64_t, int64_t)                          )
B
Bucky Kittinger 已提交
1450
);
1451 1452

REGISTER_INTRINSICS(privileged_api,
1453 1454 1455 1456
   (is_feature_active,                int(int64_t)                          )
   (activate_feature,                 void(int64_t)                         )
   (get_resource_limits,              void(int64_t,int,int,int)             )
   (set_resource_limits,              void(int64_t,int64_t,int64_t,int64_t) )
1457
   (set_active_producers,             int(int,int)                          )
1458 1459 1460 1461
   (get_blockchain_parameters_packed, int(int, int)                         )
   (set_blockchain_parameters_packed, void(int,int)                         )
   (is_privileged,                    int(int64_t)                          )
   (set_privileged,                   void(int64_t, int)                    )
1462
);
1463

1464
REGISTER_INJECTED_INTRINSICS(checktime_api,
1465
   (checktime,      void(int))
1466 1467
);

1468
REGISTER_INTRINSICS(producer_api,
B
Bucky Kittinger 已提交
1469
   (get_active_producers,      int(int, int) )
1470 1471
);

A
arhag 已提交
1472
#define DB_SECONDARY_INDEX_METHODS_SIMPLE(IDX) \
1473 1474 1475 1476 1477 1478 1479
   (db_##IDX##_store,          int(int64_t,int64_t,int64_t,int64_t,int))\
   (db_##IDX##_remove,         void(int))\
   (db_##IDX##_update,         void(int,int64_t,int))\
   (db_##IDX##_find_primary,   int(int64_t,int64_t,int64_t,int,int64_t))\
   (db_##IDX##_find_secondary, int(int64_t,int64_t,int64_t,int,int))\
   (db_##IDX##_lowerbound,     int(int64_t,int64_t,int64_t,int,int))\
   (db_##IDX##_upperbound,     int(int64_t,int64_t,int64_t,int,int))\
1480
   (db_##IDX##_end,            int(int64_t,int64_t,int64_t))\
1481 1482 1483
   (db_##IDX##_next,           int(int, int))\
   (db_##IDX##_previous,       int(int, int))

A
arhag 已提交
1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495
#define DB_SECONDARY_INDEX_METHODS_ARRAY(IDX) \
      (db_##IDX##_store,          int(int64_t,int64_t,int64_t,int64_t,int,int))\
      (db_##IDX##_remove,         void(int))\
      (db_##IDX##_update,         void(int,int64_t,int,int))\
      (db_##IDX##_find_primary,   int(int64_t,int64_t,int64_t,int,int,int64_t))\
      (db_##IDX##_find_secondary, int(int64_t,int64_t,int64_t,int,int,int))\
      (db_##IDX##_lowerbound,     int(int64_t,int64_t,int64_t,int,int,int))\
      (db_##IDX##_upperbound,     int(int64_t,int64_t,int64_t,int,int,int))\
      (db_##IDX##_end,            int(int64_t,int64_t,int64_t))\
      (db_##IDX##_next,           int(int, int))\
      (db_##IDX##_previous,       int(int, int))

D
Daniel Larimer 已提交
1496 1497 1498 1499
REGISTER_INTRINSICS( database_api,
   (db_store_i64,        int(int64_t,int64_t,int64_t,int64_t,int,int))
   (db_update_i64,       void(int,int64_t,int,int))
   (db_remove_i64,       void(int))
1500
   (db_get_i64,          int(int, int, int))
1501 1502
   (db_next_i64,         int(int, int))
   (db_previous_i64,     int(int, int))
D
Daniel Larimer 已提交
1503 1504
   (db_find_i64,         int(int64_t,int64_t,int64_t,int64_t))
   (db_lowerbound_i64,   int(int64_t,int64_t,int64_t,int64_t))
1505
   (db_upperbound_i64,   int(int64_t,int64_t,int64_t,int64_t))
A
arhag 已提交
1506
   (db_end_i64,          int(int64_t,int64_t,int64_t))
1507

A
arhag 已提交
1508 1509 1510
   DB_SECONDARY_INDEX_METHODS_SIMPLE(idx64)
   DB_SECONDARY_INDEX_METHODS_SIMPLE(idx128)
   DB_SECONDARY_INDEX_METHODS_ARRAY(idx256)
A
arhag 已提交
1511
   DB_SECONDARY_INDEX_METHODS_SIMPLE(idx_double)
1512
);
D
Daniel Larimer 已提交
1513

1514
REGISTER_INTRINSICS(crypto_api,
B
Bucky Kittinger 已提交
1515 1516
   (assert_recover_key,     void(int, int, int, int, int) )
   (recover_key,            int(int, int, int, int, int)  )
B
Bucky Kittinger 已提交
1517 1518 1519 1520
   (assert_sha256,          void(int, int, int)           )
   (assert_sha1,            void(int, int, int)           )
   (assert_sha512,          void(int, int, int)           )
   (assert_ripemd160,       void(int, int, int)           )
B
Bucky Kittinger 已提交
1521 1522 1523 1524
   (sha1,                   void(int, int, int)           )
   (sha256,                 void(int, int, int)           )
   (sha512,                 void(int, int, int)           )
   (ripemd160,              void(int, int, int)           )
1525 1526
);

M
Matias Romeo 已提交
1527 1528 1529 1530
REGISTER_INTRINSICS(permission_api,
   (check_authorization,  int(int64_t, int64_t, int, int))
);

1531
REGISTER_INTRINSICS(string_api,
B
Bucky Kittinger 已提交
1532
   (assert_is_utf8,  void(int, int, int) )
1533 1534
);

B
Bart Wyatt 已提交
1535
REGISTER_INTRINSICS(system_api,
1536 1537
   (abort,        void())
   (eosio_assert, void(int, int))
1538
   (eosio_exit,   void(int ))
1539
   (now,          int())
B
Bart Wyatt 已提交
1540 1541 1542
);

REGISTER_INTRINSICS(action_api,
1543 1544
   (read_action_data,       int(int, int)  )
   (action_data_size,       int()          )
1545
   (publication_time,   int32_t()          )
1546
   (current_receiver,   int64_t()          )
B
Bart Wyatt 已提交
1547 1548 1549
);

REGISTER_INTRINSICS(apply_context,
B
Bucky Kittinger 已提交
1550
   (require_recipient,     void(int64_t)          )
1551
   (require_authorization, void(int64_t), "require_auth", void(apply_context::*)(const account_name&))
1552
   (require_authorization, void(int64_t, int64_t), "require_auth2", void(apply_context::*)(const account_name&, const permission_name& permission))
1553
   (has_authorization,     int(int64_t), "has_auth", bool(apply_context::*)(const account_name&)const)
B
Bucky Kittinger 已提交
1554
   (is_account,            int(int64_t)           )
B
Bart Wyatt 已提交
1555 1556 1557 1558 1559
);

REGISTER_INTRINSICS(console_api,
   (prints,                void(int)       )
   (prints_l,              void(int, int)  )
D
Daniel Larimer 已提交
1560
   (printui,               void(int64_t)   )
B
Bart Wyatt 已提交
1561 1562
   (printi,                void(int64_t)   )
   (printi128,             void(int)       )
1563 1564
   (printdf,               void(double)    )
   (printff,               void(float)     )
B
Bart Wyatt 已提交
1565 1566 1567 1568
   (printn,                void(int64_t)   )
   (printhex,              void(int, int)  )
);

D
Daniel Larimer 已提交
1569
REGISTER_INTRINSICS(context_free_transaction_api,
1570 1571 1572 1573 1574
   (read_transaction,       int(int, int)            )
   (transaction_size,       int()                    )
   (expiration,             int()                    )
   (tapos_block_prefix,     int()                    )
   (tapos_block_num,        int()                    )
1575
   (get_action,             int (int, int, int, int) )
1576
   (check_auth,              void(int, int, int, int) )
D
Daniel Larimer 已提交
1577 1578 1579
);

REGISTER_INTRINSICS(transaction_api,
1580 1581 1582 1583
   (send_inline,               void(int, int)               )
   (send_context_free_inline,  void(int, int)               )
   (send_deferred,             void(int, int64_t, int, int) )
   (cancel_deferred,           void(int)                    )
1584 1585
);

D
Daniel Larimer 已提交
1586 1587 1588 1589
REGISTER_INTRINSICS(context_free_api,
   (get_context_free_data, int(int, int, int) )
)

1590
REGISTER_INTRINSICS(memory_api,
B
Bucky Kittinger 已提交
1591 1592 1593 1594
   (memcpy,                 int(int, int, int)  )
   (memmove,                int(int, int, int)  )
   (memcmp,                 int(int, int, int)  )
   (memset,                 int(int, int, int)  )
1595 1596
);

1597
REGISTER_INJECTED_INTRINSICS(softfloat_api,
B
Bucky Kittinger 已提交
1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617
      (_eosio_f32_add,       float(float, float)    )
      (_eosio_f32_sub,       float(float, float)    )
      (_eosio_f32_mul,       float(float, float)    )
      (_eosio_f32_div,       float(float, float)    )
      (_eosio_f32_min,       float(float, float)    )
      (_eosio_f32_max,       float(float, float)    )
      (_eosio_f32_copysign,  float(float, float)    )
      (_eosio_f32_abs,       float(float)           )
      (_eosio_f32_neg,       float(float)           )
      (_eosio_f32_sqrt,      float(float)           )
      (_eosio_f32_ceil,      float(float)           )
      (_eosio_f32_floor,     float(float)           )
      (_eosio_f32_trunc,     float(float)           )
      (_eosio_f32_nearest,   float(float)           )
      (_eosio_f32_eq,        int(float, float)      )
      (_eosio_f32_ne,        int(float, float)      )
      (_eosio_f32_lt,        int(float, float)      )
      (_eosio_f32_le,        int(float, float)      )
      (_eosio_f32_gt,        int(float, float)      )
      (_eosio_f32_ge,        int(float, float)      )
1618 1619 1620 1621 1622 1623 1624
      (_eosio_f64_add,       double(double, double) )
      (_eosio_f64_sub,       double(double, double) )
      (_eosio_f64_mul,       double(double, double) )
      (_eosio_f64_div,       double(double, double) )
      (_eosio_f64_min,       double(double, double) )
      (_eosio_f64_max,       double(double, double) )
      (_eosio_f64_copysign,  double(double, double) )
B
Bucky Kittinger 已提交
1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655
      (_eosio_f64_abs,       double(double)         )
      (_eosio_f64_neg,       double(double)         )
      (_eosio_f64_sqrt,      double(double)         )
      (_eosio_f64_ceil,      double(double)         )
      (_eosio_f64_floor,     double(double)         )
      (_eosio_f64_trunc,     double(double)         )
      (_eosio_f64_nearest,   double(double)         )
      (_eosio_f64_eq,        int(double, double)    )
      (_eosio_f64_ne,        int(double, double)    )
      (_eosio_f64_lt,        int(double, double)    )
      (_eosio_f64_le,        int(double, double)    )
      (_eosio_f64_gt,        int(double, double)    )
      (_eosio_f64_ge,        int(double, double)    )
      (_eosio_f32_promote,    double(float)         )
      (_eosio_f64_demote,     float(double)         )
      (_eosio_f32_trunc_i32s, int(float)            )
      (_eosio_f64_trunc_i32s, int(double)           )
      (_eosio_f32_trunc_i32u, int(float)            )
      (_eosio_f64_trunc_i32u, int(double)           )
      (_eosio_f32_trunc_i64s, int64_t(float)        )
      (_eosio_f64_trunc_i64s, int64_t(double)       )
      (_eosio_f32_trunc_i64u, int64_t(float)        )
      (_eosio_f64_trunc_i64u, int64_t(double)       )
      (_eosio_i32_to_f32,     float(int32_t)        )
      (_eosio_i64_to_f32,     float(int64_t)        )
      (_eosio_ui32_to_f32,    float(int32_t)        )
      (_eosio_ui64_to_f32,    float(int64_t)        )
      (_eosio_i32_to_f64,     double(int32_t)       )
      (_eosio_i64_to_f64,     double(int64_t)       )
      (_eosio_ui32_to_f64,    double(int32_t)       )
      (_eosio_ui64_to_f64,    double(int64_t)       )
1656
);
B
Bucky Kittinger 已提交
1657

1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668
std::istream& operator>>(std::istream& in, wasm_interface::vm_type& runtime) {
   std::string s;
   in >> s;
   if (s == "wavm")
      runtime = eosio::chain::wasm_interface::vm_type::wavm;
   else if (s == "binaryen")
      runtime = eosio::chain::wasm_interface::vm_type::binaryen;
   else
      in.setstate(std::ios_base::failbit);
   return in;
}
B
Brian Johnson 已提交
1669

D
Daniel Larimer 已提交
1670
} } /// eosio::chain