github.com/DTFN/go-ethereum@v1.4.5/cmd/clef/pythonsigner.py (about)

     1  import os,sys, subprocess
     2  from tinyrpc.transports import ServerTransport
     3  from tinyrpc.protocols.jsonrpc import JSONRPCProtocol
     4  from tinyrpc.dispatch import public,RPCDispatcher
     5  from tinyrpc.server import RPCServer
     6  
     7  """ This is a POC example of how to write a custom UI for Clef. The UI starts the
     8  clef process with the '--stdio-ui' option, and communicates with clef using standard input / output.
     9  
    10  The standard input/output is a relatively secure way to communicate, as it does not require opening any ports
    11  or IPC files. Needless to say, it does not protect against memory inspection mechanisms where an attacker
    12  can access process memory."""
    13  
    14  try:
    15      import urllib.parse as urlparse
    16  except ImportError:
    17      import urllib as urlparse
    18  
    19  class StdIOTransport(ServerTransport):
    20      """ Uses std input/output for RPC """
    21      def receive_message(self):
    22          return None, urlparse.unquote(sys.stdin.readline())
    23  
    24      def send_reply(self, context, reply):
    25          print(reply)
    26  
    27  class PipeTransport(ServerTransport):
    28      """ Uses std a pipe for RPC """
    29  
    30      def __init__(self,input, output):
    31          self.input = input
    32          self.output = output
    33  
    34      def receive_message(self):
    35          data = self.input.readline()
    36          print(">> {}".format( data))
    37          return None, urlparse.unquote(data)
    38  
    39      def send_reply(self, context, reply):
    40          print("<< {}".format( reply))
    41          self.output.write(reply)
    42          self.output.write("\n")
    43  
    44  class StdIOHandler():
    45  
    46      def __init__(self):
    47          pass
    48  
    49      @public
    50      def ApproveTx(self,req):
    51          """
    52          Example request:
    53          {
    54              "jsonrpc": "2.0",
    55              "method": "ApproveTx",
    56              "params": [{
    57                  "transaction": {
    58                      "to": "0xae967917c465db8578ca9024c205720b1a3651A9",
    59                      "gas": "0x333",
    60                      "gasPrice": "0x123",
    61                      "value": "0x10",
    62                      "data": "0xd7a5865800000000000000000000000000000000000000000000000000000000000000ff",
    63                      "nonce": "0x0"
    64                  },
    65                  "from": "0xAe967917c465db8578ca9024c205720b1a3651A9",
    66                  "call_info": "Warning! Could not validate ABI-data against calldata\nSupplied ABI spec does not contain method signature in data: 0xd7a58658",
    67                  "meta": {
    68                      "remote": "127.0.0.1:34572",
    69                      "local": "localhost:8550",
    70                      "scheme": "HTTP/1.1"
    71                  }
    72              }],
    73              "id": 1
    74          }
    75  
    76          :param transaction: transaction info
    77          :param call_info: info abou the call, e.g. if ABI info could not be
    78          :param meta: metadata about the request, e.g. where the call comes from
    79          :return: 
    80          """
    81          transaction = req.get('transaction')
    82          _from       = req.get('from')
    83          call_info   = req.get('call_info')
    84          meta        = req.get('meta')
    85  
    86          return {
    87              "approved" : False,
    88              #"transaction" : transaction,
    89    #          "from" : _from,
    90  #            "password" : None,
    91          }
    92  
    93      @public
    94      def ApproveSignData(self, req):
    95          """ Example request
    96  
    97          """
    98          return {"approved": False, "password" : None}
    99  
   100      @public
   101      def ApproveExport(self, req):
   102          """ Example request
   103  
   104          """
   105          return {"approved" : False}
   106  
   107      @public
   108      def ApproveImport(self, req):
   109          """ Example request
   110  
   111          """
   112          return { "approved" : False, "old_password": "", "new_password": ""}
   113  
   114      @public
   115      def ApproveListing(self, req):
   116          """ Example request
   117  
   118          """
   119          return {'accounts': []}
   120  
   121      @public
   122      def ApproveNewAccount(self, req):
   123          """
   124          Example request
   125  
   126          :return:
   127          """
   128          return {"approved": False,
   129                  #"password": ""
   130                  }
   131  
   132      @public
   133      def ShowError(self,message = {}):
   134          """
   135          Example request:
   136  
   137          {"jsonrpc":"2.0","method":"ShowInfo","params":{"message":"Testing 'ShowError'"},"id":1}
   138  
   139          :param message: to show
   140          :return: nothing
   141          """
   142          if 'text' in message.keys():
   143              sys.stderr.write("Error: {}\n".format( message['text']))
   144          return
   145  
   146      @public
   147      def ShowInfo(self,message = {}):
   148          """
   149          Example request
   150          {"jsonrpc":"2.0","method":"ShowInfo","params":{"message":"Testing 'ShowInfo'"},"id":0}
   151  
   152          :param message: to display
   153          :return:nothing
   154          """
   155  
   156          if 'text' in message.keys():
   157              sys.stdout.write("Error: {}\n".format( message['text']))
   158          return
   159  
   160  def main(args):
   161  
   162      cmd = ["./clef", "--stdio-ui"]
   163      if len(args) > 0 and args[0] == "test":
   164          cmd.extend(["--stdio-ui-test"])
   165      print("cmd: {}".format(" ".join(cmd)))
   166      dispatcher = RPCDispatcher()
   167      dispatcher.register_instance(StdIOHandler(), '')
   168      # line buffered
   169      p = subprocess.Popen(cmd, bufsize=1, universal_newlines=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
   170  
   171      rpc_server = RPCServer(
   172          PipeTransport(p.stdout, p.stdin),
   173          JSONRPCProtocol(),
   174          dispatcher
   175      )
   176      rpc_server.serve_forever()
   177  
   178  if __name__ == '__main__':
   179      main(sys.argv[1:])