github.com/k1rill-fedoseev/go-ethereum@v1.9.7/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 def __init__(self): 46 pass 47 48 @public 49 def ApproveTx(self,req): 50 """ 51 Example request: 52 { 53 "jsonrpc": "2.0", 54 "method": "ApproveTx", 55 "params": [{ 56 "transaction": { 57 "to": "0xae967917c465db8578ca9024c205720b1a3651A9", 58 "gas": "0x333", 59 "gasPrice": "0x123", 60 "value": "0x10", 61 "data": "0xd7a5865800000000000000000000000000000000000000000000000000000000000000ff", 62 "nonce": "0x0" 63 }, 64 "from": "0xAe967917c465db8578ca9024c205720b1a3651A9", 65 "call_info": "Warning! Could not validate ABI-data against calldata\nSupplied ABI spec does not contain method signature in data: 0xd7a58658", 66 "meta": { 67 "remote": "127.0.0.1:34572", 68 "local": "localhost:8550", 69 "scheme": "HTTP/1.1" 70 } 71 }], 72 "id": 1 73 } 74 75 :param transaction: transaction info 76 :param call_info: info abou the call, e.g. if ABI info could not be 77 :param meta: metadata about the request, e.g. where the call comes from 78 :return: 79 """ 80 transaction = req.get('transaction') 81 _from = req.get('from') 82 call_info = req.get('call_info') 83 meta = req.get('meta') 84 85 return { 86 "approved" : False, 87 #"transaction" : transaction, 88 # "from" : _from, 89 # "password" : None, 90 } 91 92 @public 93 def ApproveSignData(self, req): 94 """ Example request 95 96 """ 97 return {"approved": False, "password" : None} 98 99 @public 100 def ApproveExport(self, req): 101 """ Example request 102 103 """ 104 return {"approved" : False} 105 106 @public 107 def ApproveImport(self, req): 108 """ Example request 109 110 """ 111 return { "approved" : False, "old_password": "", "new_password": ""} 112 113 @public 114 def ApproveListing(self, req): 115 """ Example request 116 117 """ 118 return {'accounts': []} 119 120 @public 121 def ApproveNewAccount(self, req): 122 """ 123 Example request 124 125 :return: 126 """ 127 return {"approved": False, 128 #"password": "" 129 } 130 131 @public 132 def ShowError(self,message = {}): 133 """ 134 Example request: 135 136 {"jsonrpc":"2.0","method":"ShowInfo","params":{"message":"Testing 'ShowError'"},"id":1} 137 138 :param message: to show 139 :return: nothing 140 """ 141 if 'text' in message.keys(): 142 sys.stderr.write("Error: {}\n".format( message['text'])) 143 return 144 145 @public 146 def ShowInfo(self,message = {}): 147 """ 148 Example request 149 {"jsonrpc":"2.0","method":"ShowInfo","params":{"message":"Testing 'ShowInfo'"},"id":0} 150 151 :param message: to display 152 :return:nothing 153 """ 154 155 if 'text' in message.keys(): 156 sys.stdout.write("Error: {}\n".format( message['text'])) 157 return 158 159 def main(args): 160 cmd = ["clef", "--stdio-ui"] 161 if len(args) > 0 and args[0] == "test": 162 cmd.extend(["--stdio-ui-test"]) 163 print("cmd: {}".format(" ".join(cmd))) 164 dispatcher = RPCDispatcher() 165 dispatcher.register_instance(StdIOHandler(), '') 166 # line buffered 167 p = subprocess.Popen(cmd, bufsize=1, universal_newlines=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE) 168 169 rpc_server = RPCServer( 170 PipeTransport(p.stdout, p.stdin), 171 JSONRPCProtocol(), 172 dispatcher 173 ) 174 rpc_server.serve_forever() 175 176 if __name__ == '__main__': 177 main(sys.argv[1:])