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 | ||
api [2018/11/15 11:13] YerkoBits agregar ejemplo al inicio |
api [2019/07/31 20:44] (actual) YerkoBits sección "pruebas" |
||
---|---|---|---|
Línea 9: | Línea 9: | ||
Usando el archivo prosus-daemon junto con el prosus-wallet tienes un set de instrucciones JSON-RPC mucho más amplio que usando el archivo prosus-pay (que fue diseñado para experimentar botones de pago solamente) | Usando el archivo prosus-daemon junto con el prosus-wallet tienes un set de instrucciones JSON-RPC mucho más amplio que usando el archivo prosus-pay (que fue diseñado para experimentar botones de pago solamente) | ||
- | 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, |
./ | ./ | ||
- | | ||
---- | ---- | ||
+ | **Pruebas** | ||
+ | Puedes probar si funciona el JSON-RPC de **Prosus.Money**, | ||
+ | http:// | ||
- | **Contenido** | + | ... o la consola (comando curl). |
+ | curl -s -u user:pass -X POST http:// | ||
- | - | + | Si quieres conectar a un servidor remoto de Prosus.Money... |
- | - Bytecoin Node Daemon JSON RPC API | + | |
- | | + | |
- | | + | |
- | | + | |
- | 1) **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. To start the walletd you must pass a path to a 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: | + | |
- | + | ||
- | <ip> is the IPv4 address of the walletd service. If the service is on a local machine, use 127.0.0.1 instead of localhost. | + | |
- | < | + | |
- | Curl Template | + | |
- | curl -s -u < | + | |
- | Methods | + | |
- | Address and key management | + | |
- | Method Description | + | |
- | create_addresses Adds addresses into the wallet file. | + | |
- | get_addresses Returns a list of addresses extracted from the wallet file. | + | |
- | get_view_key_pair Returns a view key pair shared by addresses. | + | |
- | Balance and history of transfers | + | |
- | Method Description | + | |
- | get_status Returns combined status of walletd and bytecoind. | + | |
- | get_balance Returns balance for a single address or all addresses. | + | |
- | get_unspents Returns balance split into outputs. | + | |
- | get_transfers Allows iterating through history of transfers to/from addresses. | + | |
- | create_send_proof Creates send-proof that money has been sent to an address. | + | |
- | check_send_proof Checks correctness of the given send-proof. | + | |
- | get_transaction Returns transaction (only if it has transfer(s) to/from any address) by hash. | + | |
- | Sending money | + | |
- | Method Description | + | |
- | create_transaction Builds a transaction by specifying transfers you want to make and returns it for inspection. | + | |
- | send_transaction Sends previously created transaction to the network. | + | |
- | 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 []string Yes - Array of secret spend keys. | + | |
- | creation_timestamp uint32 No 0 Min of creation timestamps of spend keys. | + | |
- | Output | + | |
- | Field Type Description | + | |
- | secret_spend_keys []string Array of created secret spend keys. | + | |
- | addresses []string Array of created 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 []string Array of addresses. | + | |
- | view_only bool Flag indicating if wallet is 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, | + | |
- | + | ||
- | 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 []string No [] Array of addresses. | + | |
- | transaction_hash string Yes - Transaction hash. | + | |
- | message string No Empty User message. | + | |
- | Output | + | |
- | Field Type Description | + | |
- | send_proofs []string Array of created 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. | + | |
- | + | ||
- | Input (params) | + | |
- | Field Type Mandatory Default value Description | + | |
- | address string No Empty Address. | + | |
- | height_or_depth int32 No -6 Point of finality. | + | |
- | Output | + | |
- | Field Type Description | + | |
- | spendable uint64 Amount that can be spent with anonymity >= 0. | + | |
- | spendable_dust uint64 Amount that can be spend with anonymity = 0. | + | |
- | 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 string No Empty Value received in previous get_status response. | + | |
- | transaction_pool_version uint32 No 0 Value received in previous get_status response. | + | |
- | incoming_peer_count uint32 No 0 Value received in previous get_status response. | + | |
- | outgoing_peer_count uint32 No 0 Value received in previous get_status response. | + | |
- | lower_level_error string No Empty Value received in previous get_status response. | + | |
- | Output | + | |
- | Field Type Description | + | |
- | top_known_block_height uint32 Largest block height known to walletd or bytecoind. | + | |
- | top_block_height uint32 All transaction prior to that height have been processed by walletd. | + | |
- | top_block_difficulty uint64 Difficulty of top block. | + | |
- | top_block_timestamp uint32 Timestamp of top block. | + | |
- | top_block_hash string Hash of top block. | + | |
- | top_block_timestamp_median uint32 Median timestamp of top block. | + | |
- | recommended_fee_per_byte uint64 Value of fee recommended. | + | |
- | transaction_pool_version uint32 Adding or removing transaction from pool increments version. | + | |
- | incoming_peer_count uint32 Incoming peers to bytecoind. | + | |
- | outgoing_peer_count uint32 Outgoing peers from bytecoind. | + | |
- | lower_level_error string Error on lower level (bytecoind for walletd, etc). | + | |
- | 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), direction (forward) flag, and approximate chunk size (desired_transactions_count) to iterate through the transfer history. A bit more or less than desired_transactions_count can be returned, as this call always returns whole blocks. Window for the next iteration is returned as (next_from_height .. next_to_height). When this window becomes empty, iteration is finished. | + | |
- | + | ||
- | 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 string No Empty Filter by address. | + | |
- | desired_transactions_count uint32 No 2^32-1 Approx. number of transactions to return. | + | |
- | forward bool No false Direction of iteration through window. | + | |
- | from_height uint32 No 0 Start of window (not included). | + | |
- | to_height uint32 No 2^32-1 End of window (included). | + | |
- | Output | + | |
- | Field Type Description | + | |
- | blocks []Block Blocks from window. | + | |
- | unlocked_transfers []Transfer Transfers unlocked within window. | + | |
- | next_from_height uint32 Window for next iteration. | + | |
- | next_to_height uint32 Window for next iteration. | + | |
- | 9. Get unspents | + | |
- | About | + | |
- | This method returns the same information as get_balance, | + | |
- | + | ||
- | 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 string No Empty Address. | + | |
- | height_or_depth int32 No -6 Point of finality. | + | |
- | Output | + | |
- | Field Type Description | + | |
- | spendable []Output Outputs that can be spent. | + | |
- | 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, | + | |
- | + | ||
- | 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 and get_transfers call. walletd selects random outputs to mix in with your outputs, and should select them from the same finality window, otherwise you risk either losing anonymity (if you set it to low) or making transaction invalid (if you set it too high and blockchain reorganization happens). | + | |
- | + | ||
- | Setting fee_per_byte to 0 is the same as setting it to the value returned by get_status. You can use larger or smaller value to increase or decrease chance of speedy inclusion in the blockchain. | + | |
- | + | ||
- | 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 call. | + | |
- | + | ||
- | You get binary_transaction field to later pass to send_transaction, | + | |
- | + | ||
- | Input (params) | + | |
- | Field Type Mandatory Default value Description | + | |
- | transaction Transaction Yes - Partly filled transaction. | + | |
- | spend_addresses []string No Empty Addresses money will be withdrawn from. | + | |
- | any_spend_address bool No false Required if spend_address empty. | + | |
- | change_address string Yes - Address where the change will be sent to. | + | |
- | confirmed_height_or_depth int32 No -6 Confirmed point of finality. | + | |
- | fee_per_byte int64 No 0 0 to use recommended value. | + | |
- | optimization string No Empty Optimization (fusion) level. | + | |
- | save_history bool No true Flag to indicate storing transfer history. | + | |
- | Output | + | |
- | Field Type Description | + | |
- | binary_transaction string Hex of binary transaction bytes. | + | |
- | transaction Transaction Transaction for inspecting. | + | |
- | save_history_error string Only not empty for an error. | + | |
- | 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, if transaction was successfully placed into the memory pool. Result of call will be increasefee, | + | |
- | + | ||
- | Input (params) | + | |
- | Field Type Mandatory Default value Description | + | |
- | binary_transaction string Yes - Hex of binary transaction bytes. | + | |
- | Output | + | |
- | Field Type Description | + | |
- | send_result string Result of call. | + | |
- | 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 string Yes - A send proof to check. | + | |
- | Output | + | |
- | Field Type Description | + | |
- | validation_error string Result of call. Empty, if the proof is correct. | + | |
- | 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): | + | |
- | + | ||
- | $ ./ | + | |
- | $ ./walletd --wallet-file=< | + | |
- | Running a single walletd with external bytecoind on a different machine (if not using https, you can only use IP-address): | + | |
- | + | ||
- | $ ./ | + | |
- | $ ./walletd --wallet-file=< | + | |
- | Running two walletds with external bytecoind on the same machine: | + | |
- | + | ||
- | $ ./ | + | |
- | $ ./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' |