github.com/DTFN/go-ethereum@v1.4.5/cmd/clef/README.md (about) 1 Clef 2 ---- 3 Clef can be used to sign transactions and data and is meant as a replacement for geth's account management. 4 This allows DApps not to depend on geth's account management. When a DApp wants to sign data it can send the data to 5 the signer, the signer will then provide the user with context and asks the user for permission to sign the data. If 6 the users grants the signing request the signer will send the signature back to the DApp. 7 8 This setup allows a DApp to connect to a remote Ethereum node and send transactions that are locally signed. This can 9 help in situations when a DApp is connected to a remote node because a local Ethereum node is not available, not 10 synchronised with the chain or a particular Ethereum node that has no built-in (or limited) account management. 11 12 Clef can run as a daemon on the same machine, or off a usb-stick like [usb armory](https://inversepath.com/usbarmory), 13 or a separate VM in a [QubesOS](https://www.qubes-os.org/) type os setup. 14 15 16 ## Command line flags 17 Clef accepts the following command line options: 18 ``` 19 COMMANDS: 20 init Initialize the signer, generate secret storage 21 attest Attest that a js-file is to be used 22 addpw Store a credential for a keystore file 23 help Shows a list of commands or help for one command 24 25 GLOBAL OPTIONS: 26 --loglevel value log level to emit to the screen (default: 4) 27 --keystore value Directory for the keystore (default: "$HOME/.ethereum/keystore") 28 --configdir value Directory for clef configuration (default: "$HOME/.clef") 29 --networkid value Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby) (default: 1) 30 --lightkdf Reduce key-derivation RAM & CPU usage at some expense of KDF strength 31 --nousb Disables monitoring for and managing USB hardware wallets 32 --rpcaddr value HTTP-RPC server listening interface (default: "localhost") 33 --rpcport value HTTP-RPC server listening port (default: 8550) 34 --signersecret value A file containing the password used to encrypt signer credentials, e.g. keystore credentials and ruleset hash 35 --4bytedb value File containing 4byte-identifiers (default: "./4byte.json") 36 --4bytedb-custom value File used for writing new 4byte-identifiers submitted via API (default: "./4byte-custom.json") 37 --auditlog value File used to emit audit logs. Set to "" to disable (default: "audit.log") 38 --rules value Enable rule-engine (default: "rules.json") 39 --stdio-ui Use STDIN/STDOUT as a channel for an external UI. This means that an STDIN/STDOUT is used for RPC-communication with a e.g. a graphical user interface, and can be used when the signer is started by an external process. 40 --stdio-ui-test Mechanism to test interface between signer and UI. Requires 'stdio-ui'. 41 --help, -h show help 42 --version, -v print the version 43 44 ``` 45 46 47 Example: 48 ``` 49 signer -keystore /my/keystore -chainid 4 50 ``` 51 52 Check out the [tutorial](tutorial.md) for some concrete examples on how the signer works. 53 54 ## Security model 55 56 The security model of the signer is as follows: 57 58 * One critical component (the signer binary / daemon) is responsible for handling cryptographic operations: signing, private keys, encryption/decryption of keystore files. 59 * The signer binary has a well-defined 'external' API. 60 * The 'external' API is considered UNTRUSTED. 61 * The signer binary also communicates with whatever process that invoked the binary, via stdin/stdout. 62 * This channel is considered 'trusted'. Over this channel, approvals and passwords are communicated. 63 64 The general flow for signing a transaction using e.g. geth is as follows: 65 ![image](sign_flow.png) 66 67 In this case, `geth` would be started with `--externalsigner=http://localhost:8550` and would relay requests to `eth.sendTransaction`. 68 69 ## TODOs 70 71 Some snags and todos 72 73 * [ ] The signer should take a startup param "--no-change", for UIs that do not contain the capability 74 to perform changes to things, only approve/deny. Such a UI should be able to start the signer in 75 a more secure mode by telling it that it only wants approve/deny capabilities. 76 77 * [x] It would be nice if the signer could collect new 4byte-id:s/method selectors, and have a 78 secondary database for those (`4byte_custom.json`). Users could then (optionally) submit their collections for 79 inclusion upstream. 80 81 * It should be possible to configure the signer to check if an account is indeed known to it, before 82 passing on to the UI. The reason it currently does not, is that it would make it possible to enumerate 83 accounts if it immediately returned "unknown account". 84 * [x] It should be possible to configure the signer to auto-allow listing (certain) accounts, instead of asking every time. 85 * [x] Done Upon startup, the signer should spit out some info to the caller (particularly important when executed in `stdio-ui`-mode), 86 invoking methods with the following info: 87 * [x] Version info about the signer 88 * [x] Address of API (http/ipc) 89 * [ ] List of known accounts 90 * [ ] Have a default timeout on signing operations, so that if the user has not answered withing e.g. 60 seconds, the request is rejected. 91 * [ ] `account_signRawTransaction` 92 * [ ] `account_bulkSignTransactions([] transactions)` should 93 * only exist if enabled via config/flag 94 * only allow non-data-sending transactions 95 * all txs must use the same `from`-account 96 * let the user confirm, showing 97 * the total amount 98 * the number of unique recipients 99 100 * Geth todos 101 - The signer should pass the `Origin` header as call-info to the UI. As of right now, the way that info about the request is 102 put together is a bit of a hack into the http server. This could probably be greatly improved 103 - Relay: Geth should be started in `geth --external_signer localhost:8550`. 104 - Currently, the Geth APIs use `common.Address` in the arguments to transaction submission (e.g `to` field). This 105 type is 20 `bytes`, and is incapable of carrying checksum information. The signer uses `common.MixedcaseAddress`, which 106 retains the original input. 107 - The Geth api should switch to use the same type, and relay `to`-account verbatim to the external api. 108 109 * [x] Storage 110 * [x] An encrypted key-value storage should be implemented 111 * See [rules.md](rules.md) for more info about this. 112 113 * Another potential thing to introduce is pairing. 114 * To prevent spurious requests which users just accept, implement a way to "pair" the caller with the signer (external API). 115 * Thus geth/mist/cpp would cryptographically handshake and afterwards the caller would be allowed to make signing requests. 116 * This feature would make the addition of rules less dangerous. 117 118 * Wallets / accounts. Add API methods for wallets. 119 120 ## Communication 121 122 ### External API 123 124 The signer listens to HTTP requests on `rpcaddr`:`rpcport`, with the same JSONRPC standard as Geth. The messages are 125 expected to be JSON [jsonrpc 2.0 standard](http://www.jsonrpc.org/specification). 126 127 Some of these call can require user interaction. Clients must be aware that responses 128 may be delayed significanlty or may never be received if a users decides to ignore the confirmation request. 129 130 The External API is **untrusted** : it does not accept credentials over this api, nor does it expect 131 that requests have any authority. 132 133 ### UI API 134 135 The signer has one native console-based UI, for operation without any standalone tools. 136 However, there is also an API to communicate with an external UI. To enable that UI, 137 the signer needs to be executed with the `--stdio-ui` option, which allocates the 138 `stdin`/`stdout` for the UI-api. 139 140 An example (insecure) proof-of-concept of has been implemented in `pythonsigner.py`. 141 142 The model is as follows: 143 144 * The user starts the UI app (`pythonsigner.py`). 145 * The UI app starts the `signer` with `--stdio-ui`, and listens to the 146 process output for confirmation-requests. 147 * The `signer` opens the external http api. 148 * When the `signer` receives requests, it sends a `jsonrpc` request via `stdout`. 149 * The UI app prompts the user accordingly, and responds to the `signer` 150 * The `signer` signs (or not), and responds to the original request. 151 152 ## External API 153 154 See the [external api changelog](extapi_changelog.md) for information about changes to this API. 155 156 ### Encoding 157 - number: positive integers that are hex encoded 158 - data: hex encoded data 159 - string: ASCII string 160 161 All hex encoded values must be prefixed with `0x`. 162 163 ## Methods 164 165 ### account_new 166 167 #### Create new password protected account 168 169 The signer will generate a new private key, encrypts it according to [web3 keystore spec](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition) and stores it in the keystore directory. 170 The client is responsible for creating a backup of the keystore. If the keystore is lost there is no method of retrieving lost accounts. 171 172 #### Arguments 173 174 None 175 176 #### Result 177 - address [string]: account address that is derived from the generated key 178 - url [string]: location of the keyfile 179 180 #### Sample call 181 ```json 182 { 183 "id": 0, 184 "jsonrpc": "2.0", 185 "method": "account_new", 186 "params": [] 187 } 188 189 { 190 "id": 0, 191 "jsonrpc": "2.0", 192 "result": { 193 "address": "0xbea9183f8f4f03d427f6bcea17388bdff1cab133", 194 "url": "keystore:///my/keystore/UTC--2017-08-24T08-40-15.419655028Z--bea9183f8f4f03d427f6bcea17388bdff1cab133" 195 } 196 } 197 ``` 198 199 ### account_list 200 201 #### List available accounts 202 List all accounts that this signer currently manages 203 204 #### Arguments 205 206 None 207 208 #### Result 209 - array with account records: 210 - account.address [string]: account address that is derived from the generated key 211 - account.type [string]: type of the 212 - account.url [string]: location of the account 213 214 #### Sample call 215 ```json 216 { 217 "id": 1, 218 "jsonrpc": "2.0", 219 "method": "account_list" 220 } 221 222 { 223 "id": 1, 224 "jsonrpc": "2.0", 225 "result": [ 226 { 227 "address": "0xafb2f771f58513609765698f65d3f2f0224a956f", 228 "type": "account", 229 "url": "keystore:///tmp/keystore/UTC--2017-08-24T07-26-47.162109726Z--afb2f771f58513609765698f65d3f2f0224a956f" 230 }, 231 { 232 "address": "0xbea9183f8f4f03d427f6bcea17388bdff1cab133", 233 "type": "account", 234 "url": "keystore:///tmp/keystore/UTC--2017-08-24T08-40-15.419655028Z--bea9183f8f4f03d427f6bcea17388bdff1cab133" 235 } 236 ] 237 } 238 ``` 239 240 ### account_signTransaction 241 242 #### Sign transactions 243 Signs a transactions and responds with the signed transaction in RLP encoded form. 244 245 #### Arguments 246 2. transaction object: 247 - `from` [address]: account to send the transaction from 248 - `to` [address]: receiver account. If omitted or `0x`, will cause contract creation. 249 - `gas` [number]: maximum amount of gas to burn 250 - `gasPrice` [number]: gas price 251 - `value` [number:optional]: amount of Wei to send with the transaction 252 - `data` [data:optional]: input data 253 - `nonce` [number]: account nonce 254 3. method signature [string:optional] 255 - The method signature, if present, is to aid decoding the calldata. Should consist of `methodname(paramtype,...)`, e.g. `transfer(uint256,address)`. The signer may use this data to parse the supplied calldata, and show the user. The data, however, is considered totally untrusted, and reliability is not expected. 256 257 258 #### Result 259 - signed transaction in RLP encoded form [data] 260 261 #### Sample call 262 ```json 263 { 264 "id": 2, 265 "jsonrpc": "2.0", 266 "method": "account_signTransaction", 267 "params": [ 268 { 269 "from": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db", 270 "gas": "0x55555", 271 "gasPrice": "0x1234", 272 "input": "0xabcd", 273 "nonce": "0x0", 274 "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0", 275 "value": "0x1234" 276 } 277 ] 278 } 279 ``` 280 Response 281 282 ```json 283 { 284 "jsonrpc": "2.0", 285 "id": 67, 286 "error": { 287 "code": -32000, 288 "message": "Request denied" 289 } 290 } 291 ``` 292 #### Sample call with ABI-data 293 294 295 ```json 296 { 297 "jsonrpc": "2.0", 298 "method": "account_signTransaction", 299 "params": [ 300 { 301 "from": "0x694267f14675d7e1b9494fd8d72fefe1755710fa", 302 "gas": "0x333", 303 "gasPrice": "0x1", 304 "nonce": "0x0", 305 "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0", 306 "value": "0x0", 307 "data": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012" 308 }, 309 "safeSend(address)" 310 ], 311 "id": 67 312 } 313 ``` 314 Response 315 316 ```json 317 { 318 "jsonrpc": "2.0", 319 "id": 67, 320 "result": { 321 "raw": "0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663", 322 "tx": { 323 "nonce": "0x0", 324 "gasPrice": "0x1", 325 "gas": "0x333", 326 "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0", 327 "value": "0x0", 328 "input": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012", 329 "v": "0x26", 330 "r": "0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e", 331 "s": "0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663", 332 "hash": "0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e" 333 } 334 } 335 } 336 ``` 337 338 Bash example: 339 ```bash 340 #curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"account_signTransaction","params":[{"from":"0x694267f14675d7e1b9494fd8d72fefe1755710fa","gas":"0x333","gasPrice":"0x1","nonce":"0x0","to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0", "value":"0x0", "data":"0x4401a6e40000000000000000000000000000000000000000000000000000000000000012"},"safeSend(address)"],"id":67}' http://localhost:8550/ 341 342 {"jsonrpc":"2.0","id":67,"result":{"raw":"0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663","tx":{"nonce":"0x0","gasPrice":"0x1","gas":"0x333","to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0","value":"0x0","input":"0x4401a6e40000000000000000000000000000000000000000000000000000000000000012","v":"0x26","r":"0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e","s":"0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663","hash":"0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e"}}} 343 ``` 344 345 346 ### account_sign 347 348 #### Sign data 349 Signs a chunk of data and returns the calculated signature. 350 351 #### Arguments 352 - account [address]: account to sign with 353 - data [data]: data to sign 354 355 #### Result 356 - calculated signature [data] 357 358 #### Sample call 359 ```json 360 { 361 "id": 3, 362 "jsonrpc": "2.0", 363 "method": "account_sign", 364 "params": [ 365 "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db", 366 "0xaabbccdd" 367 ] 368 } 369 ``` 370 Response 371 372 ```json 373 { 374 "id": 3, 375 "jsonrpc": "2.0", 376 "result": "0x5b6693f153b48ec1c706ba4169960386dbaa6903e249cc79a8e6ddc434451d417e1e57327872c7f538beeb323c300afa9999a3d4a5de6caf3be0d5ef832b67ef1c" 377 } 378 ``` 379 380 ### account_ecRecover 381 382 #### Recover address 383 Derive the address from the account that was used to sign data from the data and signature. 384 385 #### Arguments 386 - data [data]: data that was signed 387 - signature [data]: the signature to verify 388 389 #### Result 390 - derived account [address] 391 392 #### Sample call 393 ```json 394 { 395 "id": 4, 396 "jsonrpc": "2.0", 397 "method": "account_ecRecover", 398 "params": [ 399 "0xaabbccdd", 400 "0x5b6693f153b48ec1c706ba4169960386dbaa6903e249cc79a8e6ddc434451d417e1e57327872c7f538beeb323c300afa9999a3d4a5de6caf3be0d5ef832b67ef1c" 401 ] 402 } 403 ``` 404 Response 405 406 ```json 407 { 408 "id": 4, 409 "jsonrpc": "2.0", 410 "result": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db" 411 } 412 413 ``` 414 415 ### account_import 416 417 #### Import account 418 Import a private key into the keystore. The imported key is expected to be encrypted according to the web3 keystore 419 format. 420 421 #### Arguments 422 - account [object]: key in [web3 keystore format](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition) (retrieved with account_export) 423 424 #### Result 425 - imported key [object]: 426 - key.address [address]: address of the imported key 427 - key.type [string]: type of the account 428 - key.url [string]: key URL 429 430 #### Sample call 431 ```json 432 { 433 "id": 6, 434 "jsonrpc": "2.0", 435 "method": "account_import", 436 "params": [ 437 { 438 "address": "c7412fc59930fd90099c917a50e5f11d0934b2f5", 439 "crypto": { 440 "cipher": "aes-128-ctr", 441 "cipherparams": { 442 "iv": "401c39a7c7af0388491c3d3ecb39f532" 443 }, 444 "ciphertext": "eb045260b18dd35cd0e6d99ead52f8fa1e63a6b0af2d52a8de198e59ad783204", 445 "kdf": "scrypt", 446 "kdfparams": { 447 "dklen": 32, 448 "n": 262144, 449 "p": 1, 450 "r": 8, 451 "salt": "9a657e3618527c9b5580ded60c12092e5038922667b7b76b906496f021bb841a" 452 }, 453 "mac": "880dc10bc06e9cec78eb9830aeb1e7a4a26b4c2c19615c94acb632992b952806" 454 }, 455 "id": "09bccb61-b8d3-4e93-bf4f-205a8194f0b9", 456 "version": 3 457 }, 458 ] 459 } 460 ``` 461 Response 462 463 ```json 464 { 465 "id": 6, 466 "jsonrpc": "2.0", 467 "result": { 468 "address": "0xc7412fc59930fd90099c917a50e5f11d0934b2f5", 469 "type": "account", 470 "url": "keystore:///tmp/keystore/UTC--2017-08-24T11-00-42.032024108Z--c7412fc59930fd90099c917a50e5f11d0934b2f5" 471 } 472 } 473 ``` 474 475 ### account_export 476 477 #### Export account from keystore 478 Export a private key from the keystore. The exported private key is encrypted with the original passphrase. When the 479 key is imported later this passphrase is required. 480 481 #### Arguments 482 - account [address]: export private key that is associated with this account 483 484 #### Result 485 - exported key, see [web3 keystore format](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition) for 486 more information 487 488 #### Sample call 489 ```json 490 { 491 "id": 5, 492 "jsonrpc": "2.0", 493 "method": "account_export", 494 "params": [ 495 "0xc7412fc59930fd90099c917a50e5f11d0934b2f5" 496 ] 497 } 498 ``` 499 Response 500 501 ```json 502 { 503 "id": 5, 504 "jsonrpc": "2.0", 505 "result": { 506 "address": "c7412fc59930fd90099c917a50e5f11d0934b2f5", 507 "crypto": { 508 "cipher": "aes-128-ctr", 509 "cipherparams": { 510 "iv": "401c39a7c7af0388491c3d3ecb39f532" 511 }, 512 "ciphertext": "eb045260b18dd35cd0e6d99ead52f8fa1e63a6b0af2d52a8de198e59ad783204", 513 "kdf": "scrypt", 514 "kdfparams": { 515 "dklen": 32, 516 "n": 262144, 517 "p": 1, 518 "r": 8, 519 "salt": "9a657e3618527c9b5580ded60c12092e5038922667b7b76b906496f021bb841a" 520 }, 521 "mac": "880dc10bc06e9cec78eb9830aeb1e7a4a26b4c2c19615c94acb632992b952806" 522 }, 523 "id": "09bccb61-b8d3-4e93-bf4f-205a8194f0b9", 524 "version": 3 525 } 526 } 527 ``` 528 529 530 531 ## UI API 532 533 These methods needs to be implemented by a UI listener. 534 535 By starting the signer with the switch `--stdio-ui-test`, the signer will invoke all known methods, and expect the UI to respond with 536 denials. This can be used during development to ensure that the API is (at least somewhat) correctly implemented. 537 See `pythonsigner`, which can be invoked via `python3 pythonsigner.py test` to perform the 'denial-handshake-test'. 538 539 All methods in this API uses object-based parameters, so that there can be no mixups of parameters: each piece of data is accessed by key. 540 541 See the [ui api changelog](intapi_changelog.md) for information about changes to this API. 542 543 OBS! A slight deviation from `json` standard is in place: every request and response should be confined to a single line. 544 Whereas the `json` specification allows for linebreaks, linebreaks __should not__ be used in this communication channel, to make 545 things simpler for both parties. 546 547 ### ApproveTx 548 549 Invoked when there's a transaction for approval. 550 551 552 #### Sample call 553 554 Here's a method invocation: 555 ```bash 556 557 curl -i -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"account_signTransaction","params":[{"from":"0x694267f14675d7e1b9494fd8d72fefe1755710fa","gas":"0x333","gasPrice":"0x1","nonce":"0x0","to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0", "value":"0x0", "data":"0x4401a6e40000000000000000000000000000000000000000000000000000000000000012"},"safeSend(address)"],"id":67}' http://localhost:8550/ 558 ``` 559 560 ```json 561 562 { 563 "jsonrpc": "2.0", 564 "id": 1, 565 "method": "ApproveTx", 566 "params": [ 567 { 568 "transaction": { 569 "from": "0x0x694267f14675d7e1b9494fd8d72fefe1755710fa", 570 "to": "0x0x07a565b7ed7d7a678680a4c162885bedbb695fe0", 571 "gas": "0x333", 572 "gasPrice": "0x1", 573 "value": "0x0", 574 "nonce": "0x0", 575 "data": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012", 576 "input": null 577 }, 578 "call_info": [ 579 { 580 "type": "WARNING", 581 "message": "Invalid checksum on to-address" 582 }, 583 { 584 "type": "Info", 585 "message": "safeSend(address: 0x0000000000000000000000000000000000000012)" 586 } 587 ], 588 "meta": { 589 "remote": "127.0.0.1:48486", 590 "local": "localhost:8550", 591 "scheme": "HTTP/1.1" 592 } 593 } 594 ] 595 } 596 597 ``` 598 599 The same method invocation, but with invalid data: 600 ```bash 601 602 curl -i -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"account_signTransaction","params":[{"from":"0x694267f14675d7e1b9494fd8d72fefe1755710fa","gas":"0x333","gasPrice":"0x1","nonce":"0x0","to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0", "value":"0x0", "data":"0x4401a6e40000000000000002000000000000000000000000000000000000000000000012"},"safeSend(address)"],"id":67}' http://localhost:8550/ 603 ``` 604 605 ```json 606 607 { 608 "jsonrpc": "2.0", 609 "id": 1, 610 "method": "ApproveTx", 611 "params": [ 612 { 613 "transaction": { 614 "from": "0x0x694267f14675d7e1b9494fd8d72fefe1755710fa", 615 "to": "0x0x07a565b7ed7d7a678680a4c162885bedbb695fe0", 616 "gas": "0x333", 617 "gasPrice": "0x1", 618 "value": "0x0", 619 "nonce": "0x0", 620 "data": "0x4401a6e40000000000000002000000000000000000000000000000000000000000000012", 621 "input": null 622 }, 623 "call_info": [ 624 { 625 "type": "WARNING", 626 "message": "Invalid checksum on to-address" 627 }, 628 { 629 "type": "WARNING", 630 "message": "Transaction data did not match ABI-interface: WARNING: Supplied data is stuffed with extra data. \nWant 0000000000000002000000000000000000000000000000000000000000000012\nHave 0000000000000000000000000000000000000000000000000000000000000012\nfor method safeSend(address)" 631 } 632 ], 633 "meta": { 634 "remote": "127.0.0.1:48492", 635 "local": "localhost:8550", 636 "scheme": "HTTP/1.1" 637 } 638 } 639 ] 640 } 641 642 643 ``` 644 645 One which has missing `to`, but with no `data`: 646 647 648 ```json 649 650 { 651 "jsonrpc": "2.0", 652 "id": 3, 653 "method": "ApproveTx", 654 "params": [ 655 { 656 "transaction": { 657 "from": "", 658 "to": null, 659 "gas": "0x0", 660 "gasPrice": "0x0", 661 "value": "0x0", 662 "nonce": "0x0", 663 "data": null, 664 "input": null 665 }, 666 "call_info": [ 667 { 668 "type": "CRITICAL", 669 "message": "Tx will create contract with empty code!" 670 } 671 ], 672 "meta": { 673 "remote": "signer binary", 674 "local": "main", 675 "scheme": "in-proc" 676 } 677 } 678 ] 679 } 680 ``` 681 682 ### ApproveExport 683 684 Invoked when a request to export an account has been made. 685 686 #### Sample call 687 688 ```json 689 690 { 691 "jsonrpc": "2.0", 692 "id": 7, 693 "method": "ApproveExport", 694 "params": [ 695 { 696 "address": "0x0000000000000000000000000000000000000000", 697 "meta": { 698 "remote": "signer binary", 699 "local": "main", 700 "scheme": "in-proc" 701 } 702 } 703 ] 704 } 705 706 ``` 707 708 ### ApproveListing 709 710 Invoked when a request for account listing has been made. 711 712 #### Sample call 713 714 ```json 715 716 { 717 "jsonrpc": "2.0", 718 "id": 5, 719 "method": "ApproveListing", 720 "params": [ 721 { 722 "accounts": [ 723 { 724 "type": "Account", 725 "url": "keystore:///home/bazonk/.ethereum/keystore/UTC--2017-11-20T14-44-54.089682944Z--123409812340981234098123409812deadbeef42", 726 "address": "0x123409812340981234098123409812deadbeef42" 727 }, 728 { 729 "type": "Account", 730 "url": "keystore:///home/bazonk/.ethereum/keystore/UTC--2017-11-23T21-59-03.199240693Z--cafebabedeadbeef34098123409812deadbeef42", 731 "address": "0xcafebabedeadbeef34098123409812deadbeef42" 732 } 733 ], 734 "meta": { 735 "remote": "signer binary", 736 "local": "main", 737 "scheme": "in-proc" 738 } 739 } 740 ] 741 } 742 743 ``` 744 745 746 ### ApproveSignData 747 748 #### Sample call 749 750 ```json 751 { 752 "jsonrpc": "2.0", 753 "id": 4, 754 "method": "ApproveSignData", 755 "params": [ 756 { 757 "address": "0x123409812340981234098123409812deadbeef42", 758 "raw_data": "0x01020304", 759 "message": "\u0019Ethereum Signed Message:\n4\u0001\u0002\u0003\u0004", 760 "hash": "0x7e3a4e7a9d1744bc5c675c25e1234ca8ed9162bd17f78b9085e48047c15ac310", 761 "meta": { 762 "remote": "signer binary", 763 "local": "main", 764 "scheme": "in-proc" 765 } 766 } 767 ] 768 } 769 770 ``` 771 772 ### ShowInfo 773 774 The UI should show the info to the user. Does not expect response. 775 776 #### Sample call 777 778 ```json 779 { 780 "jsonrpc": "2.0", 781 "id": 9, 782 "method": "ShowInfo", 783 "params": [ 784 { 785 "text": "Tests completed" 786 } 787 ] 788 } 789 790 ``` 791 792 ### ShowError 793 794 The UI should show the info to the user. Does not expect response. 795 796 ```json 797 798 { 799 "jsonrpc": "2.0", 800 "id": 2, 801 "method": "ShowError", 802 "params": [ 803 { 804 "text": "Testing 'ShowError'" 805 } 806 ] 807 } 808 809 ``` 810 811 ### OnApproved 812 813 `OnApprovedTx` is called when a transaction has been approved and signed. The call contains the return value that will be sent to the external caller. The return value from this method is ignored - the reason for having this callback is to allow the ruleset to keep track of approved transactions. 814 815 When implementing rate-limited rules, this callback should be used. 816 817 TLDR; Use this method to keep track of signed transactions, instead of using the data in `ApproveTx`. 818 819 ### OnSignerStartup 820 821 This method provide the UI with information about what API version the signer uses (both internal and external) aswell as build-info and external api, 822 in k/v-form. 823 824 Example call: 825 ```json 826 827 { 828 "jsonrpc": "2.0", 829 "id": 1, 830 "method": "OnSignerStartup", 831 "params": [ 832 { 833 "info": { 834 "extapi_http": "http://localhost:8550", 835 "extapi_ipc": null, 836 "extapi_version": "2.0.0", 837 "intapi_version": "1.2.0" 838 } 839 } 840 ] 841 } 842 843 ``` 844 845 846 ### Rules for UI apis 847 848 A UI should conform to the following rules. 849 850 * A UI MUST NOT load any external resources that were not embedded/part of the UI package. 851 * For example, not load icons, stylesheets from the internet 852 * Not load files from the filesystem, unless they reside in the same local directory (e.g. config files) 853 * A Graphical UI MUST show the blocky-identicon for ethereum addresses. 854 * A UI MUST warn display approproate warning if the destination-account is formatted with invalid checksum. 855 * A UI MUST NOT open any ports or services 856 * The signer opens the public port 857 * A UI SHOULD verify the permissions on the signer binary, and refuse to execute or warn if permissions allow non-user write. 858 * A UI SHOULD inform the user about the `SHA256` or `MD5` hash of the binary being executed 859 * A UI SHOULD NOT maintain a secondary storage of data, e.g. list of accounts 860 * The signer provides accounts 861 * A UI SHOULD, to the best extent possible, use static linking / bundling, so that requried libraries are bundled 862 along with the UI. 863 864