chainlib-eth

Ethereum implementation of the chainlib interface
Info | Log | Files | Refs | README | LICENSE

encode.py (2801B)


      1 # standard imports
      2 import re
      3 import logging
      4 
      5 # external imports
      6 from chainlib.eth.contract import (
      7         ABIContractType,
      8         ABIContractEncoder,
      9         )
     10 from chainlib.eth.constant import ZERO_ADDRESS
     11 from chainlib.eth.constant import ZERO_CONTENT
     12 
     13 logg = logging.getLogger(__name__)
     14 
     15 
     16 class CLIEncoder(ABIContractEncoder):
     17 
     18     __re_uint = r'^([uU])[int]*([0-9]+)?$'
     19     __re_bytes = r'^([bB])[ytes]*([0-9]+)?$'
     20     __re_string = r'^([sS])[tring]*$'
     21     __re_address = r'^([aA])[ddress]*?$'
     22     __translations = [
     23             'to_uint',
     24             'to_bytes',
     25             'to_string',
     26             'to_address',
     27             ]
     28 
     29     def __init__(self, signature=None):
     30         super(CLIEncoder, self).__init__()
     31         self.signature = signature
     32         if signature != None:
     33             self.method(signature)
     34 
     35     def to_uint(self, typ):
     36         s = None
     37         a = None
     38         m = re.match(self.__re_uint, typ)
     39         if m == None:
     40             return None
     41 
     42         n = m.group(2)
     43         if m.group(2) == None:
     44             n = 256
     45         s = 'UINT256'.format(m.group(2))
     46         a = getattr(ABIContractType, s)
     47         return (s, a)
     48 
     49 
     50     def to_bytes(self, typ):
     51         s = None
     52         a = None
     53         m = re.match(self.__re_bytes, typ)
     54         if m == None:
     55             return None
     56         
     57         n = m.group(2)
     58         if n == None:
     59             n = 32
     60         s = 'BYTES{}'.format(n)
     61         a = getattr(ABIContractType, s)
     62         return (s, a)
     63 
     64 
     65     def to_address(self, typ):
     66         s = None
     67         a = None
     68         m = re.match(self.__re_address, typ)
     69         if m == None:
     70             return None
     71         
     72         s = 'ADDRESS'
     73         a = getattr(ABIContractType, s)
     74         return (s, a)
     75 
     76 
     77     def to_string(self, typ):
     78         m = re.match(self.__re_string, typ)
     79         if m == None:
     80             return None
     81         s = 'STRING'
     82         a = getattr(ABIContractType, s)
     83         return (s, a)
     84 
     85 
     86     def translate(self, typ, val):
     87         r = None
     88         for tr in self.__translations:
     89             r = getattr(self, tr)(typ)
     90             if r != None:
     91                 break
     92         if r == None:
     93             raise ValueError('no translation for type {}'.format(typ))
     94         logg.debug('type {} translated to {}'.format(typ, r[0]))
     95         if r[0] != 'STRING':
     96             if int(val, 16) == 0:
     97                 if r[0][0] == 'B':
     98                     val = ZERO_CONTENT
     99                 elif r[0][0] == 'A':
    100                     val = ZERO_ADDRESS
    101         return (r[1], val,)
    102 
    103 
    104     def add_from(self, arg):
    105         logg.debug('arg {}'.format(arg))
    106         (typ, val) = arg.split(':', maxsplit=1)
    107         (real_typ, val) = self.translate(typ, val)
    108         if self.signature != None:
    109             self.typ(real_typ)
    110         fn = getattr(self, real_typ.value)
    111         fn(val)