Diferencias
Muestra las diferencias entre dos versiones de la página.
Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa Última revisión Ambos lados, revisión siguiente | ||
api [2019/02/02 18:52] YerkoBits advertencia para texto sin editar |
api [2019/07/31 15:35] YerkoBits |
||
---|---|---|---|
Línea 11: | Línea 11: | ||
Como ejemplo aparte, los parámetros para iniciar el prosus-daemon para levantar un block-explorer, | Como ejemplo aparte, los parámetros para iniciar el prosus-daemon para levantar un block-explorer, | ||
./ | ./ | ||
- | | ||
- | ---- | + | Puedes probar si funciona el JSON-RPC de **Prosus.Money**, |
+ | http:// | ||
- | FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME | + | ... o la consola (comando curl) |
+ | curl -s -u user:pass -X POST http:// | ||
- | **Contenido** | ||
- | |||
- | - | ||
- | - | ||
- | - | ||
- | - | ||
- | - | ||
- | |||
- | |||
- | ====== Bytecoin Wallet Daemon JSON RPC API ====== | ||
- | |||
- | |||
- | ## Introduction | ||
- | |||
- | The Bytecoin Wallet Daemon (`walletd`, Bytecoin RPC Wallet) is designed to manage a user's account while operating together with a [Bytecoin Node Daemon](Bytecoin-Node-Daemon-JSON-RPC-API). To start the `walletd` you must pass a path to a [wallet file](Wallet-File) as a command-line parameter which identifies the context the service will work within. | ||
- | |||
- | ## Service Location | ||
- | |||
- | By default, the Bytecoin Wallet Daemon is only bound to `127.0.0.1` (`localhost`) interface, so it can only be reached from the same computer it runs on. To bind it to all interfaces, use `--walletd-bind-address=0.0.0.0: | ||
- | |||
- | To make a JSON PRC request to the `walletd` you should make an HTTP POST request to an entry point: | ||
- | ``` | ||
- | http://< | ||
- | ``` | ||
- | where: | ||
- | * `< | ||
- | * `< | ||
- | |||
- | ## Curl Template | ||
- | |||
- | ``` | ||
- | curl -s -u < | ||
- | ``` | ||
- | |||
- | ## Methods | ||
- | |||
- | ### Address and key management | ||
- | |||
- | | Method | ||
- | |---------------------------------------------------------------------------------|-------------------------------------------------------------| | ||
- | | [`create_addresses`](Bytecoin-Wallet-Daemon-JSON-RPC-API# | ||
- | | [`get_addresses`](Bytecoin-Wallet-Daemon-JSON-RPC-API# | ||
- | | [`get_view_key_pair`](Bytecoin-Wallet-Daemon-JSON-RPC-API# | ||
- | |||
- | ### Balance and history of transfers | ||
- | |||
- | | Method | ||
- | |---------------------------------------------------------------------------------|-------------------------------------------------------------------------------| | ||
- | | [`get_status`](Bytecoin-Wallet-Daemon-JSON-RPC-API# | ||
- | | [`get_balance`](Bytecoin-Wallet-Daemon-JSON-RPC-API# | ||
- | | [`get_unspents`](Bytecoin-Wallet-Daemon-JSON-RPC-API# | ||
- | | [`get_transfers`](Bytecoin-Wallet-Daemon-JSON-RPC-API# | ||
- | | [`create_send_proof`](Bytecoin-Wallet-Daemon-JSON-RPC-API# | ||
- | | [`check_send_proof`](Bytecoin-Wallet-Daemon-JSON-RPC-API# | ||
- | | [`get_transaction`](Bytecoin-Wallet-Daemon-JSON-RPC-API# | ||
- | |||
- | ### Sending money | ||
- | |||
- | | Method | ||
- | |------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------- | | ||
- | | [`create_transaction`](Bytecoin-Wallet-Daemon-JSON-RPC-API# | ||
- | | [`send_transaction`](Bytecoin-Wallet-Daemon-JSON-RPC-API# | ||
- | |||
- | ----------------------------------------------------------------------------------------------------------------------- | ||
- | |||
- | ### 1. Create Addresses | ||
- | |||
- | #### About | ||
- | |||
- | Either adds new or imports existing addresses (with corresponding spend keys) into a wallet file. To generate a new random key pair (and address, of course), you append an empty string to a `secret_spend_keys` array. To import an existing address, you append its secret spend key to a `secret_spend_keys` array. If you import existing addresses created some time ago, specify `creation_timestamp` so the `walletd` can rescan the blockchain starting from that point of time, looking for transactions to/from those addresses. | ||
- | |||
- | Adding an existing secret spend key is not an error, it will just return a corresponding address together with that key. | ||
- | |||
- | This method returns arrays of both addresses and secret spend keys, where each address corresponds to each secret key. | ||
- | |||
- | Before this method returns, it performs `fdatasync` on the wallet file, so if you add lots of addresses, it makes sense to batch them instead of calling this method individually per address. | ||
- | |||
- | #### Input (params) | ||
- | |||
- | | Field | Type | Mandatory | Default value | Description | ||
- | |----------------------|------------|-----------|---------------|-------------------------------------------| | ||
- | | `secret_spend_keys` | ||
- | | `creation_timestamp` | `uint32` | ||
- | |||
- | #### Output | ||
- | |||
- | | Field | Type | Description | ||
- | |----------------------|------------|-------------------------------------| | ||
- | | `secret_spend_keys` | ||
- | | `addresses` | ||
- | |||
- | #### Example 1 | ||
- | |||
- | Let's create two new addresses. | ||
- | |||
- | __Input:__ | ||
- | ``` | ||
- | curl -s -u user:pass -X POST http:// | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | }' | ||
- | ``` | ||
- | |||
- | __Output:__ | ||
- | ``` | ||
- | { | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | ], | ||
- | " | ||
- | " | ||
- | " | ||
- | ] | ||
- | } | ||
- | } | ||
- | ``` | ||
- | |||
- | ### 2. Get Addresses | ||
- | |||
- | #### About | ||
- | |||
- | Returns an array of all addresses stored in a wallet file. If `view_only` flag is `true`, there are no | ||
- | secret spend keys in the file, so the `walletd` is allowed to spend money from any address. | ||
- | |||
- | #### Input (params) | ||
- | |||
- | Empty | ||
- | |||
- | #### Output | ||
- | |||
- | | Field | Type | Description | ||
- | |--------------|------------|-----------------------------------------| | ||
- | | `addresses` | ||
- | | `view_only` | ||
- | |||
- | #### Example 1 | ||
- | |||
- | Let's request all the addresses in the current wallet file. | ||
- | |||
- | __Input:__ | ||
- | |||
- | ``` | ||
- | curl -s -u user:pass -X POST http:// | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | }' | ||
- | ``` | ||
- | |||
- | __Output:__ | ||
- | ``` | ||
- | { | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | ], | ||
- | " | ||
- | } | ||
- | } | ||
- | ``` | ||
- | |||
- | ### 3. Get View Key Pair | ||
- | |||
- | #### About | ||
- | |||
- | Returns a view key pair common for all addresses in a wallet file. | ||
- | |||
- | #### Input (params) | ||
- | |||
- | Empty | ||
- | |||
- | #### Output | ||
- | |||
- | | Field | Type | Description | ||
- | |-------------------|----------|------------------| | ||
- | | `public_view_key` | `string` | Public view key. | | ||
- | | `secret_view_key` | `string` | Secret view key. | | ||
- | |||
- | #### Example 1 | ||
- | |||
- | Let's receive a pair of view keys from the current wallet file. | ||
- | |||
- | __Input:__ | ||
- | ``` | ||
- | curl -s -u user:pass -X POST http:// | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | }' | ||
- | ``` | ||
- | |||
- | __Output:__ | ||
- | ``` | ||
- | { | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | } | ||
- | } | ||
- | ``` | ||
- | |||
- | ### 4. Create Send Proof | ||
- | |||
- | #### About | ||
- | |||
- | Creates a send proof certifying that the money has actually been sent by the caller in a specified transaction to an address. | ||
- | If you leave the field `addresses` empty, you get a proof for every address used in the transaction, | ||
- | If you set an array of addresses, you get a proof for every address actually used in a transaction. The GUI client can use the address book in an attempt to guess addresses in case there is no history stored for a particular transaction. | ||
- | |||
- | The field `message` is any user text. It will be included in the proof and become part of it so that changing the `message` would be impossible without destroying the proof validity. So a user can include personal info or some challenge there to prove that they have really created the proof. | ||
- | |||
- | Returns an array of generated proofs or empty array if no proofs has been generated (this usually happens if no money has been actually sent to specified addresses in specified transaction) | ||
- | |||
- | #### Input (params) | ||
- | |||
- | | Field | Type | Mandatory | Default value | Description | ||
- | |---------------------|------------|-----------|---------------|---------------------| | ||
- | | `addresses` | ||
- | | `transaction_hash` | ||
- | | `message` | ||
- | |||
- | #### Output | ||
- | |||
- | | Field | Type | Description | ||
- | |-------------------|------------|--------------------------| | ||
- | | `send_proofs` | ||
- | |||
- | ### 5. Get balance | ||
- | |||
- | #### About | ||
- | |||
- | Gets balance of specified address (or all addresses) taking in account specified confirmation blocks count. | ||
- | Clients, which regard some block height as ' | ||
- | |||
- | Returns balanced split into 3 categories - `spendable` is the sum of all unlocked unspent non-dust outputs created prior to specified height_or_depth. `spendable_dust` is the same for dust outputs. It can be spent only by specifying anonymity `0` in `create_tranasaction` call. `locked_or_unconfirmed` is sum of all locked or unconfirmed unspent outputs. | ||
- | |||
- | If you need introspection into actual outputs, call [`get_unspents`](Bytecoin-Wallet-Daemon-JSON-RPC-API# | ||
- | |||
- | #### Input (params) | ||
- | |||
- | | Field | Type | Mandatory | Default value | Description | ||
- | |--------------------- |----------|-----------|---------------|--------------------| | ||
- | | `address` | ||
- | | `height_or_depth` | ||
- | |||
- | #### Output | ||
- | |||
- | | Field | Type | Description | ||
- | |-------------------------|----------|------------------------------------------------------------| | ||
- | | `spendable` | ||
- | | `spendable_dust` | ||
- | | `locked_or_unconfirmed` | `uint64` | Amount that will be available at some point in the future. | | ||
- | |||
- | #### Example 1 | ||
- | |||
- | Let's get balance for all addresses under a depth of 10 blocks. | ||
- | |||
- | __Input:__ | ||
- | ``` | ||
- | curl -s -u user:pass -X POST http:// | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | }' | ||
- | ``` | ||
- | |||
- | __Output:__ | ||
- | ``` | ||
- | { | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | } | ||
- | } | ||
- | ``` | ||
- | |||
- | ### Example 2 | ||
- | |||
- | Let's get balance for address `2AGmhxRPbK3BtiyUz7vc4hHTj4n2cPdiWTHXgfHmPow5gr83GAkEsKLTE8muA6umGAEU78k7L4LmyAi7Efk4EwKoShnPYwR` over a height of 1526550. | ||
- | |||
- | __Input:__ | ||
- | ``` | ||
- | curl -s -u user:pass -X POST http:// | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | } | ||
- | }' | ||
- | ``` | ||
- | |||
- | __Output:__ | ||
- | ``` | ||
- | { | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | } | ||
- | } | ||
- | ``` | ||
- | |||
- | ### 6. Get status | ||
- | |||
- | #### About | ||
- | |||
- | Get status about state of walletd and bytecoind. If you specify all input parameters, and they are equal to the current state of the `walletd`, you will get response only when some of them change. Most simple way to accomplish this is just sending previous response as the next request. | ||
- | |||
- | #### Input (params) | ||
- | |||
- | | Field | Type | Mandatory | Default value | Description | ||
- | |----------------------------|----------|-----------|---------------|---------------------------------------------------| | ||
- | | `top_block_hash` | ||
- | | `transaction_pool_version` | `uint32` | No | `0` | Value received in previous `get_status` response. | | ||
- | | `incoming_peer_count` | ||
- | | `outgoing_peer_count` | ||
- | | `lower_level_error` | ||
- | |||
- | #### Output | ||
- | |||
- | | Field | Type | Description | ||
- | |------------------------------------|----------|------------------------------------------------------------------------------------------| | ||
- | | `top_known_block_height` | ||
- | | `top_block_height` | ||
- | | `top_block_difficulty` | ||
- | | `top_block_timestamp` | ||
- | | `top_block_hash` | ||
- | | `top_block_timestamp_median` | ||
- | | `recommended_fee_per_byte` | ||
- | | `transaction_pool_version` | ||
- | | `incoming_peer_count` | ||
- | | `outgoing_peer_count` | ||
- | | `lower_level_error` | ||
- | | `next_block_effective_median_size` | `uint32` | Created transaction raw size should be less this value, otherwise will not fit in block. | | ||
- | |||
- | #### Example 1 | ||
- | |||
- | Let's do a regular status request. | ||
- | |||
- | __Input:__ | ||
- | ``` | ||
- | curl -s -u user:pass -X POST http:// | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | }' | ||
- | ``` | ||
- | |||
- | __Output:__ | ||
- | ``` | ||
- | { | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | } | ||
- | } | ||
- | ``` | ||
- | |||
- | ### 7. Get transaction | ||
- | |||
- | #### About | ||
- | |||
- | Returns transaction by hash (only if it contains at least one transfer to/from any of wallet addresses). | ||
- | |||
- | If transaction is not found, will return a transaction with default fields (check for empty `hash` field) | ||
- | |||
- | #### Input (params) | ||
- | |||
- | | Field | Type | Mandatory | Default value | Description | ||
- | |--------|----------|-----------|---------------|--------------------| | ||
- | | `hash` | `string` | Yes | - | Hex of hash bytes. | | ||
- | |||
- | #### Output | ||
- | |||
- | | Field | Type | Description | ||
- | |---------------|---------------|------------------------| | ||
- | | `transaction` | `Transaction` | Resultant transaction. | | ||
- | |||
- | ### 8. Get transfers | ||
- | |||
- | #### About | ||
- | |||
- | This is how you iterate through the history of transfers to/from wallet addresses. If you specify address, it will filter transfers with that address (anyway you should compare address of transfer to desired address yourself, because this filter is not exact and will return excess transfers). If you set address to empty, you will get all transfers to/from any address stored in wallet file. | ||
- | |||
- | You specify window (`from_height` .. `to_height`), | ||
- | |||
- | If you specify window that includes `top_block + 1`, you will get transfers residing in transaction memory pool. | ||
- | |||
- | This method returns block only if it contains transaction we are interested into. Also transaction will be included in block only if it contains transfer we are interested into. So we get filtered view of blockchain, omitting parts which walletd cannot parse using keys stored in wallet file. | ||
- | |||
- | ### Twists with locked outputs | ||
- | |||
- | Some transactions are locked until specific block height or block timestamp. When parsing returned transfers you should look into `locked` field, and if it is true, you should avoid counting incoming balance from that transfer. | ||
- | |||
- | In addition to blocks with transfers, this method also returns transfers from prior blocks, unlocked by block height or timestamp of blocks in window you specified. So for locked transfers, you will get them in `unlocked_transfers` as soon as they are unlocked. This is the point you should count their incoming balances. | ||
- | |||
- | |||
- | #### Input (params) | ||
- | |||
- | | Field | Type | Mandatory | Default value | Description | ||
- | |------------------------------|----------|-----------|---------------|-------------------------------------------| | ||
- | | `address` | ||
- | | `desired_transactions_count` | `uint32` | No | `2^32-1` | ||
- | | `forward` | ||
- | | `from_height` | ||
- | | `to_height` | ||
- | |||
- | #### Output | ||
- | |||
- | | Field | Type | Description | ||
- | |----------------------|--------------|-----------------------------------| | ||
- | | `blocks` | ||
- | | `unlocked_transfers` | `[]Transfer` | Transfers unlocked within window. | | ||
- | | `next_from_height` | ||
- | | `next_to_height` | ||
- | |||
- | ### 9. Get unspents | ||
- | |||
- | #### About | ||
- | |||
- | This method returns the same information as [`get_balance`](Bytecoin-Wallet-Daemon-JSON-RPC-API# | ||
- | |||
- | Outputs corresponding to `spendable` and `spendable_dust` balance will be returned in `spendable` array, to distinguish them you should look into `output.is_dust` field. | ||
- | |||
- | #### Input (params) | ||
- | |||
- | | Field | Type | Mandatory | Default value | Description | ||
- | |----------------------|----------|-----------|---------------|--------------------| | ||
- | | `address` | ||
- | | `height_or_depth` | ||
- | |||
- | #### Output | ||
- | |||
- | | Field | Type | Description | ||
- | |-------------------------|------------|-------------------------------------------------------------| | ||
- | | `spendable` | ||
- | | `locked_or_unconfirmed` | `[]Output` | Outputs that will be available at some point in the future. | | ||
- | |||
- | #### Example 1 | ||
- | |||
- | Let's view unpsents for address `2AGmhxRPbK3BtiyUz7vc4hHTj4n2cPdiWTHXgfHmPow5gr83GAkEsKLTE8muA6umGAEU78k7L4LmyAi7Efk4EwKoShnPYwR` under a depth of 10 blocks. | ||
- | |||
- | __Input:__ | ||
- | ``` | ||
- | curl -s -u user:pass -X POST http:// | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | } | ||
- | }' | ||
- | ``` | ||
- | |||
- | __Output:__ | ||
- | ``` | ||
- | { | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | { | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | } | ||
- | ] | ||
- | } | ||
- | } | ||
- | ``` | ||
- | |||
- | ### 10. Create transaction | ||
- | |||
- | #### About | ||
- | |||
- | Create and sign transaction by specifying transfers to make. | ||
- | |||
- | If you set `spend_addresses`, | ||
- | If you leave `spend_addresses` empty, you should also set `any_spend_address` to true, as a protection against bug in your code accidentally leaving spend_address empty. In this case the call can spend all balance of all addresses in a wallet. | ||
- | |||
- | Usually it is impossible to find set of outputs to transfer exact sum you specify, so `change_address` is required. | ||
- | |||
- | `confirmed_height_or_depth` should be set to the same value you use for your [`get_balance`](Bytecoin-Wallet-Daemon-JSON-RPC-API# | ||
- | |||
- | Setting `fee_per_byte` to 0 is the same as setting it to the value returned by [`get_status`](Bytecoin-Wallet-Daemon-JSON-RPC-API# | ||
- | |||
- | You should fill in the following fields of transaction: | ||
- | |||
- | If you leave `optimization` field empty, walletd will use normal optimization of output denominations (fusion) when creating transaction. This works well when ratio of transactions sent to received is around 1. You can use `minimal` setting for wallets receiving far less transactions than sending, saving a bit of fees. You should use `aggressive` for wallets recieving far more transactions than sending, this setting will use every opportunity to fuse larger number of identical outputs together. As maximum transaction size is limited by block median size, you can give more room for optimization by setting anonymity to as low value as possible. Moreover, if anonymity is set to 0, wallet will prioritize optimizing out dust and crazy (large but not round) denominations of outputs. | ||
- | |||
- | You can set `save_history` to false if you save transfers you make in your own database. In case you need to generate send proof later, you will use transfer information from your database as an input to [`create_send_proof`](Bytecoin-Wallet-Daemon-JSON-RPC-API# | ||
- | |||
- | You get `binary_transaction` field to later pass to [`send_transaction`](Bytecoin-Wallet-Daemon-JSON-RPC-API# | ||
- | |||
- | #### Input (params) | ||
- | |||
- | | Field | Type | Mandatory | Default value | Description | ||
- | |-----------------------------|---------------|-----------|---------------|--------------------------------------------| | ||
- | | `transaction` | ||
- | | `spend_addresses` | ||
- | | `any_spend_address` | ||
- | | `change_address` | ||
- | | `confirmed_height_or_depth` | `int32` | ||
- | | `fee_per_byte` | ||
- | | `optimization` | ||
- | | `save_history` | ||
- | |||
- | #### Output | ||
- | |||
- | | Field | Type | Description | ||
- | |----------------------|---------------|-----------------------------------| | ||
- | | `binary_transaction` | `string` | ||
- | | `transaction` | ||
- | | `save_history_error` | `string` | ||
- | |||
- | #### Example 1 | ||
- | |||
- | Let's create a transaction, | ||
- | |||
- | __Input:__ | ||
- | ``` | ||
- | curl -s -u user:pass -X POST http:// | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | { | ||
- | " | ||
- | " | ||
- | } | ||
- | ] | ||
- | }, | ||
- | " | ||
- | " | ||
- | ], | ||
- | " | ||
- | " | ||
- | } | ||
- | }' | ||
- | ``` | ||
- | |||
- | __Output:__ | ||
- | ``` | ||
- | TODO | ||
- | ``` | ||
- | |||
- | ### 11. Send transaction | ||
- | |||
- | #### About | ||
- | |||
- | Place the (previously created) transaction into the memory pool for immediate sending to the p2p network. Note, that if bytecoind is not connected to internet, this method will nevertheless succeed. Moreover, in the situation of high transaction traffic your transaction may be eventually displaced from the memory pools of all nodes in the network. | ||
- | |||
- | Result of call will be `broadcast`, | ||
- | Result of call will be `increasefee`, | ||
- | |||
- | #### Input (params) | ||
- | |||
- | | Field | Type | Mandatory | Default value | Description | ||
- | |------------------------------|----------|-----------|---------------|----------------------------------| | ||
- | | `binary_transaction` | ||
- | |||
- | #### Output | ||
- | |||
- | | Field | Type | Description | ||
- | |----------------------|--------------|------------------| | ||
- | | `send_result` | ||
- | |||
- | ### 12. Check Send Proof | ||
- | |||
- | #### About | ||
- | |||
- | Checks that given send proof is valid and correct. | ||
- | |||
- | Result of the call will be empty value of `validation_error`, | ||
- | |||
- | #### Input (params) | ||
- | |||
- | | Field | Type | Mandatory | Default value | Description | ||
- | |------------------------------|----------|-----------|---------------|----------------------------------| | ||
- | | `send_proof` | ||
- | |||
- | #### Output | ||
- | |||
- | | Field | Type | Description | ||
- | |----------------------|--------------|--------------------------------------------------| | ||
- | | `validation_error` | ||
- | |||
- | #### Example 1 | ||
- | |||
- | Let's check a send proof, created by the `create_send_proof` method. | ||
- | |||
- | __Input:__ | ||
- | ``` | ||
- | curl -s -u user:pass -X POST http:// | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | } | ||
- | }' | ||
- | ``` | ||
- | __Output:__ | ||
- | ``` | ||
- | { | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | } | ||
- | } | ||
- | ``` | ||
---- | ---- | ||
- | |||
- | |||
- | |||
- | |||
- | |||
- | 2) **Service location** | ||
- | |||
- | By default, Bytecoin Node Service (bytecoind, Node Daemon) is bound only to 127.0.0.1 (localhost) interface, so can be accessed only from the same computer it runs on. This is done to reduce number of external attack vectors. bytecoind itself has access to only public information, | ||
- | |||
- | To make a JSON PRC request to the bytecoind you should make an HTTP POST request to an entry point: | ||
- | |||
- | http://< | ||
- | where: | ||
- | |||
- | <ip> is IPv4 address of bytecoind service. If the service is on local machine, use 127.0.0.1 instead of localhost. | ||
- | < | ||
- | Curl template | ||
- | curl -s -u < | ||
- | |||
- | **Methods** | ||
- | |||
- | **Getting information about blockchain** | ||
- | |||
- | **Method Description** | ||
- | |||
- | get_status Returns status of bytecoind. | ||
- | sync_blocks Gets blockchain blocks for walletd and block explorer sync. | ||
- | sync_mem_pool Gets difference to transaction pool. | ||
- | check_send_proof Checks validity of send proof. | ||
- | Creating transactions | ||
- | Method Description | ||
- | get_random_outputs Is used by walletd to get mix-ins when building transaction. | ||
- | send_transaction Adds transaction to pool. Usually should be called through walletd. | ||
- | Mining (new version) | ||
- | Method Description | ||
- | get_currency_id Returns hash of genesis block. | ||
- | get_block_template Gets block for mining. | ||
- | submit_block Submits mined block. | ||
- | Mining (legacy version) | ||
- | Method Description | ||
- | getcurrencyid Returns hash of genesis block. | ||
- | getblocktemplate Gets block for mining. | ||
- | submitblock Submits mined block. | ||
- | getlastblockheader Gets last block header. | ||
- | getblockheaderbyhash Gets block header by hash. | ||
- | getblockheaderbyheight Gets block header by height. Warning: This legacy method starts counting from 1, so if you set height to 5000, you will get header with height 4999. | ||
- | |||
- | 3) **Design notes** | ||
- | |||
- | Bytecoin is split into two separate services - bytecoind and walletd. This is a direct consequence of the anonymity concept Bytecoin is built upon. | ||
- | |||
- | bytecoind service is responsible for P2P connections and consensus, it can assemble transactions into blocks, check transactions validity, synchronize and grow blockchain, but it cannot look inside transactions to see transfers between addresses, because this requires access to user secrets (wallet) to do so. | ||
- | |||
- | Here comes walletd that is designed to work with user wallet being run with a wallet file as a mandatory argument. After getting chain of blocks from bytecoind, walletd sifts through all transactions with wallet keys to see transfers from and to addresses stored in that wallet file. | ||
- | |||
- | Though this separation is perfect, the most common case is running bytecoind and walletd on the same computer at the same time. That's why walletd has a local copy of bytecoind built-in. If you run walletd without --bytecoind-remote-address=< | ||
- | |||
- | You cannot have several bytecoinds running on the same machine, because bytecoind requires exclusive access to blockchain database stored in Bytecoin data folder. (kind-of exception is running one for mainnet and one for testnet, this works because there is separate Bytecoin data folder for testnet) | ||
- | |||
- | In the meantime, you can have as many walletds running as you need, but the same wallet file (actually, wallet file with the same view key) cannot be open by more than one walletd. This is because walletd requires exclusive access to wallet cache database with a name derived from wallet file view key, stored in Bytecoin data folder. | ||
- | |||
- | Security notice: If you operate large sums of money, you should always run bytecoind in separate process, so that potential attacks exploiting security vulnerabilities in p2p network code will not get access to address space where wallet keys are stored. | ||
- | |||
- | Note about secrets on command line: walletd requires wallet password and HTTP basic authentication parameters to be used by JSON API. It expects them from the standard input (typed by user after launching), because secrets on a command line are security risk. So, if you wish to run walletd from script without user interaction, | ||
- | |||
- | On Linux and Mac OSX | ||
- | $ echo -e "< | ||
- | On Windows | ||
- | C:\> (echo < | ||
- | On Windows, if wallet password is empty, we need special syntax to echo empty line | ||
- | C:\> (echo( & echo < | ||
- | Handy examples | ||
- | Running a single walletd with built-in bytecoind and default parameters: | ||
- | |||
- | $ ./walletd --wallet-file=< | ||
- | Running a single walletd with external bytecoind on the same machine (in beta you can only use 127.0.0.1 instead of localhost): | ||
- | |||
- | $ ./bytecoind | ||
- | $ ./walletd --wallet-file=< | ||
- | Running a single walletd with external bytecoind on a different machine (if not using https, you can only use IP-address): | ||
- | |||
- | $ ./bytecoind | ||
- | $ ./walletd --wallet-file=< | ||
- | Running two walletds with external bytecoind on the same machine: | ||
- | |||
- | $ ./bytecoind | ||
- | $ ./walletd --wallet-file=< | ||
- | $ ./walletd --wallet-file=< | ||
- | We had to specify different bind port for accessing second walletd, because port 8070 is already used by first walletd. | ||
- | |||
- | We can check them both in GUI wallet, selecting " | ||
- | |||
- | Running walletd with external bytecoind on a remote server via https (when using https, you can only use full DNS name): | ||
- | |||
- | $ ./walletd --wallet-file=< | ||
- | On your server, you should run bytecoind normally with Nginx HTTPS proxy (or amazon load balancer) configured with valid certificate (https:// | ||
- | |||
- | 4) **Incoming payment processing for e-shop or exchange** | ||
- | |||
- | Overall description | ||
- | |||
- | We presume that blockchain will never be reorganized beyond n_confirmations constant, we predefine. | ||
- | |||
- | We store finality_height in the database with initial value of 0. When the blockchain is advanced, we move finality_height forward, trailing top block height by n_confirmations and getting all transfers between old and new finality_height in the process, then modifying incoming balances of corresponding addresses in the database. When the blockchain is retracted, we keep finality_height as is. Can blockchain be really retracted? First, if some side chain grows beyond main chain, main chain is temporarily retracted. Second, if walletd or bytecoind database is erased (probably as a part of version upgrade), or restored from earlier backup. In any case, blockchain height will soon increase and we will continue advancing our finality_height. Here is an infinite loop to track incoming funds (pseudocode): | ||
- | |||
- | const n_confirmations = 10 | ||
- | var status | ||
- | while true: | ||
- | var was_hash = status.top_block_hash | ||
- | var was_pool_version = status.transaction_pool_version | ||
- | status = WALLETD.get_status(status) // waits for changes to status | ||
- | // code to update confirmed transaction in our DB for order processing | ||
- | if status.top_block_height > DB.finality_height + n_confirmations: | ||
- | result = WALLETD.get_transfers(from_height: | ||
- | DB.begin_transaction() | ||
- | foreach block in result.blocks: | ||
- | foreach tx in block.transactions: | ||
- | foreach transfer in tx.transfers: | ||
- | if (not transfer.locked) and transfer.ours and transfer.amount > 0: | ||
- | DB.add_incoming_confirmed(transfer.address, | ||
- | foreach transfer in result.unlocked_transfers: | ||
- | if transfer.ours and transfer.amount > 0: | ||
- | DB.add_incoming_confirmed(transfer.address, | ||
- | DB.finality_height = status.top_block_height - n_confirmations | ||
- | DB.commit_transaction() | ||
- | // code to update unconfirmed transaction in our DB for showing in user's account web interface | ||
- | if status.top_block_hash != was_hash or status.transaction_pool_version != was_pool_version: | ||
- | result = WALLETD.get_transfers(from_height: | ||
- | DB.begin_transaction() | ||
- | DB.clear_unconfirmed() | ||
- | foreach block in result.blocks: | ||
- | foreach tx in block.transactions: | ||
- | foreach transfer in tx.transfers: | ||
- | if (not transfer.locked) and transfer.ours and transfer.amount > 0: | ||
- | DB.add_incoming_unconfirmed(transfer.address, | ||
- | DB.commit_transaction() | ||
- | When the order is created by user in e-shop, or user needs a new incoming address on an exchange, we create and associate a new address like this (pseudocode): | ||
- | |||
- | result = WALLETD.create_addresses(["" | ||
- | DB.begin_transaction() | ||
- | DB.save_address_keys(result.spend_keys[0]) // we store keys in our db for backup | ||
- | DB.create_order(order_data, | ||
- | DB.commit_transaction() | ||
- | In e-shop when the incoming balance of address corresponding to some order reaches order price, we decrease incoming balance and set the order for shipment. In an exchange, incoming funds become directly available to the user as soon as they are confirmed. | ||
- | |||
- | 5) **Introduction** | ||
- | |||
- | Historically Bytecoin uses various formats for storing keys. Current version is V2, it is used by old GUI wallet and old Payment Gate daemon. The new Bytecoin also uses V2 file format with some twists (see below). | ||
- | |||
- | File structure | ||
- | Wallet file is designed to store a list of addresses (minimum one) with corresponding keys and is encrypted with ChaCha8 algorithm. Specifying no password encrypts with a key derived from the empty string. | ||
- | |||
- | Each address has a unique spend key pair, but they all share the common view key pair, so from user's perspective, | ||
- | |||
- | Common view key pair is on purpose. In Bytecoin transactions are anonymous, finding transactions corresponding to some address requires scanning all transaction in blockchain performing slow computations per view key part of the address. Several dozens of different view keys would be enough to exceed modern PC processing capabilities. | ||
- | |||
- | Creation timestamp is also stored in wallet file, this allows skipping scanning (significant) part of blockchain prior to the wallet creation. | ||
- | |||
- | Deterministic vs non-deterministic | ||
- | V2 wallet file uses non-deterministic key generation, each key is random. So you should back up wallet file after adding addresses to it, otherwise you risk losing keys for new addresses. This will change in V3. | ||
- | |||
- | View-only wallet | ||
- | View-only wallet file is created by zeroing private spend keys in existing wallet file. When such a file is open by walletd, it allows viewing transaction corresponding to addresses it stores, but does not allow spending. | ||
- | |||
- | Transaction history | ||
- | In Bytecoin, if you do not save addresses you sent money to, you cannot get this information later from blockchain and reveal those addresses. That's why transaction history is an important component being worth backing up. | ||
- | |||
- | The old Bytecoin stores history of transactions it sent in the tail section of V2 file, right after keys. In contrast, the new Bytecoin stores history in the < | ||
- | |||
- | Interoperability with old Bytecoin | ||
- | The old Bytecoin' | ||
- | |||
- | You can make new Bytecoin' | ||
- | |||
- | Opening such file by an old Bytecoin will make it rescan blockchain recreating wallet cache in tail section. | ||
- | |||
- | Interoperability with simplewallet | ||
- | simplewallet uses V1 wallet file format. The new Bytecoin' |