btcs

bitcoin script parser/evaluator/compiler/decompiler
git clone git://jb55.com/btcs
Log | Files | Refs | README | LICENSE

script_num.c (4070B)


      1 
      2 #include "script_num.h"
      3 #include "alloc.h"
      4 #include "val.h"
      5 #include <limits.h>
      6 #include <inttypes.h>
      7 
      8 /**
      9  * Numeric opcodes (OP_1ADD, etc) are restricted to operating on 4-byte
     10  * integers. The semantics are subtle, though: operands must be in the range
     11  * [-2^31 +1...2^31 -1], but results may overflow (and are valid as long as they
     12  * are not used in a subsequent numeric operation). struct num enforces those
     13  * semantics by storing results as an int64 and allowing out-of-range values to
     14  * be returned, but throwing an exception if arithmetic is done or the result is
     15  * interpreted as an integer.
     16  */
     17 
     18 
     19 void
     20 sn_from_int(s64 n, struct num *sn) {
     21   sn->ind = -1;
     22   sn->val = n;
     23 }
     24 
     25 
     26 /* enum sn_result */
     27 /* sn_to_int(struct num *sn, int *res) { */
     28 /*   if (sn_overflowed(sn)) { */
     29 /*     return SN_ERR_OVERFLOWED_INT; */
     30 /*   } */
     31 /* } */
     32 
     33 
     34 void sn_serialize(struct num *sn, u8 *buf, int bufsize, u16 *len) {
     35   u8 *p = buf;
     36 
     37   if(sn->val == 0) {
     38     *len = 0;
     39     return;
     40   }
     41 
     42   const int neg = sn->val < 0;
     43   u64 absvalue = neg ? -(sn->val) : sn->val;
     44 
     45   while(absvalue) {
     46     *(p++) = absvalue & 0xff;
     47     assert((p - buf) <= bufsize);
     48     absvalue >>= 8;
     49   }
     50 
     51   //    - If the most significant byte is >= 0x80 and the value is positive, push a
     52   //    new zero-byte to make the significant byte < 0x80 again.
     53 
     54   //    - If the most significant byte is >= 0x80 and the value is negative, push a
     55   //    new 0x80 byte that will be popped off when converting to an integral.
     56 
     57   //    - If the most significant byte is < 0x80 and the value is negative, add
     58   //    0x80 to it, since it will be subtracted and interpreted as a negative when
     59   //    converting to an integral.
     60 
     61   if (*(p - 1) & 0x80)
     62     *(p++) = neg ? 0x80 : 0;
     63   else if (neg)
     64     *(p - 1) |= 0x80;
     65 
     66   *len = p - buf;
     67 }
     68 
     69 static inline int
     70 int_overflowed(s64 val) {
     71   return val < INT_MIN || val > INT_MAX;
     72 }
     73 
     74 
     75 int
     76 sn_overflowed(struct num *num) {
     77   return int_overflowed(num->val);
     78 }
     79 
     80 
     81 s64
     82 int_from_data(u8 *data, u16 size) {
     83   s64 result = 0;
     84 
     85   if (size == 0)
     86     return 0;
     87 
     88   for (size_t i = 0; i != size; ++i)
     89     result |= (s64)((data[i]) << 8*i);
     90 
     91   // If the input vector's most significant byte is 0x80, remove it from
     92   // the result's msb and return a negative.
     93   if (data[size-1] & 0x80) {
     94     return -((s64)(result & ~(0x80ULL << (8 * (size - 1)))));
     95   }
     96 
     97   return result;
     98 }
     99 
    100 
    101 enum sn_result
    102 sn_from_data(u8 *data, u16 size, struct num **num) {
    103   u16 ind;
    104   s64 i;
    105   if (size > 4)
    106     return SN_ERR_OVERFLOWED_INT;
    107   i = int_from_data(data, size);
    108   /* printf("%" PRId64" okkkk\n", i); */
    109   *num = num_pool_new(&ind);
    110   (*num)->val = i;
    111   (*num)->ind = ind;
    112   return SN_SUCCESS;
    113 }
    114 
    115 
    116 // Return a script num only if it's still a 4-byte integer
    117 enum sn_result sn_from_val(struct val val, struct num ** sn) {
    118 
    119   switch (val.type) {
    120   case VT_SMALLINT:
    121   case VT_SCRIPTNUM:
    122     *sn = num_pool_get(val.ind);
    123     assert((*sn)->ind == val.ind);
    124     assert(*sn);
    125 
    126     // we're trying to return a scriptnum that is larger than 4 bytes. This is not
    127     // a valid scriptnum at this point. return an error.
    128     if (sn_overflowed(*sn)) {
    129       *sn = 0;
    130       return SN_ERR_OVERFLOWED_INT;
    131     }
    132 
    133     if (val.type == VT_SMALLINT)
    134       (*sn)->val = val.ind;
    135 
    136     return SN_SUCCESS;
    137   case VT_RAW:
    138   case VT_DATA: {
    139     u8 *data;
    140     u32 size;
    141     enum sn_result res;
    142     assert(val.ind != -1);
    143     data = byte_pool_get(val.ind, &size);
    144     return sn_from_data(data, size, sn);
    145   }
    146   }
    147 
    148   printf("type: %d\n", val.type);
    149   assert(!"sn_from_val: unhandled");
    150 
    151   return SN_SUCCESS;
    152 }
    153 
    154 struct val
    155 sn_to_val(struct num *sn) {
    156   struct val val;
    157   struct num *snref;
    158   u16 ind;
    159 
    160   if (sn_overflowed(sn)) {
    161     u16 ind, len;
    162     static u8 tmp[8];
    163     sn_serialize(sn, tmp, 8, &len);
    164     u8 *data = byte_pool_new(len, &ind);
    165     memcpy(data, tmp, len);
    166     val.type = VT_DATA;
    167     val.ind = ind;
    168   }
    169   else
    170   {
    171     val.type = VT_SCRIPTNUM;
    172     if (sn->ind > -1)
    173       val.ind = sn->ind;
    174     else {
    175       snref = num_pool_new(&ind);
    176       snref->val = sn->val;
    177       val.ind = ind;
    178     }
    179 
    180   }
    181   return val;
    182 }