github.com/luckypickle/go-ethereum-vet@v1.14.2/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:])