github.com/core-coin/go-core/v2@v2.1.9/cmd/clef/README.md (about)

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