Three asynchronous tasks should be added to CoinSpark wallets.

The first is fetching the missing genesis transaction when a new asset has been added to the Asset Type List not from genesis metadata. The second is checking asset validity, which is performed in response to various events and repeated once per day for every visible asset. The third is checking the asset balances in unspent transaction outputs added to the Asset Balance List.

The exact conditions under which each task is triggered are provided below. You should take steps to ensure that each task is not performed simultaneously by more than one thread in parallel. Although doing this would not cause any significant problems, it will be wasteful of computer and network resources. If an asynchronous task is triggered while it is already in progress, wait until it has completed, then run it again immediately. Each asynchronous task keeps track of its own timing through various fields in the data model, so there is no problem with running a task several times in immediate succession.

Fetching genesis transactions

This asynchronous task should be triggered by any of these conditions:

Begin this task by scanning the Asset Type List for entries which fulfil all of the following conditions:

  • Either genTxID or genesis is null.
  • The isVisible field is true.

For each such asset, carry out the following task:

  1. Obtain the assetRef for this asset from the Asset Type List. If the assetRef is null, report an error, set isVisible to false and stop here. (This should never happen in practice.)
  2. Retrieve the block from the bitcoin blockchain whose block number is assetRef.blockNum. If the block cannot be retrieved, report an error and stop here.
  3. Extract the bitcoin transaction starting at byte offset assetRef.txOffset within that block. If a transaction cannot be extracted, report an error, set isVisible to false and stop here.
  4. Calculate the bitcoin txid of the extracted transaction. If the first two bytes of this txid do not match assetRef.txIDPrefix then report an error, set isVisible to false and stop here.
  5. Try to extract a CoinSparkGenesis from the transaction. If none is present then report an error, set isVisible to false and stop here.
  6. Update the asset in the Asset Type List as follows:
    • Set genTxID to the txid of the extracted bitcoin transaction.
    • Set genesis to contain the extracted CoinSparkGenesis.
  7. Redraw the displayed asset balances and asset list in the user interface if they are visible.
  8. Trigger the asynchronous checking of asset validity.

Checking asset validity

This asynchronous task should be triggered by any of these conditions:

Begin this task by scanning the Asset Type List for entries which fulfil all of the following conditions:

  • Both genTxID and genesis are not null.
  • The isVisible field is true.
  • Any one of the following:
    • The validChecked field is null.
    • The validChecked field is more than 24 hours in the past.
    • The validFailures field is greater than 0 and validChecked is more than an hour ago. If fromSource is genesis and validFailures is less than 60 then 30 seconds should be used for this interval instead of one hour.

For each asset matching these conditions, carry out the following task:

  1. Set the asset’s validChecked field to the current date/time.
  2. Try to extract the JSON asset specification from the asset web page specified by the asset’s genTxID and genesis. Do not yet update the stored webPageJSON field for the asset.
  3. If the web page or JSON is not available, increment validFailures for the asset. If validFailures is now 1, alert the user that the asset’s web page is not valid. Stop here.
  4. Try to retrieve the asset’s contract using the contract_url field of the JSON. Do not yet update the stored contractContent and contractMIME fields for the asset.
  5. If the contract is not available, increment validFailures for the asset. If validFailures is now 1, alert the user that the asset’s contract is not available. Stop here.
  6. Calculate the asset hash from the retrieved JSON and contract content.
  7. Check that this calculated asset hash matches the asset hash prefix stored in the genesis.assetHash field for this asset. Compare only as many bytes are as available in the genesis.assetHash field.
  8. If the hash prefixes do not match, increment validFailures for the asset. If validFailures is now 1, alert the user that key asset parameters and/or the asset’s contract have been changed. Stop here.
  9. This step is recommended but can be skipped since other users of the same asset can detect the problem: If the contract is in PDF format, check that the PDF embeds no external resources, since those would enable the PDF’s appearance to be changed without changing the hash calculated from the raw content of the PDF file. If the PDF contains external resources, increment validFailures for the asset. If validFailures is now 1, alert the user that the asset’s contract cannot be verified due to external resources. Stop here.
  10. Store the JSON specification in the webPageJSON field for the asset.
  11. Set the contractContent and contractMIMEType fields based on the contract retrieved.
  12. Set the asset’s validFailures field to 0.
  13. Redraw the displayed asset balances and asset list in the user interface if they are visible.
  14. Trigger the asynchronous checking of asset balances.

Checking asset balances

This asynchronous task should be triggered by any of these conditions:

Begin this task by scanning the Asset Balance List for entries which fulfil any one of the following conditions:

  • Either the qtyChecked field is null.
  • Or the qtyFailures field is between 0 and 119 (inclusive) and qtyChecked is more than 5 seconds ago.

Group the entries in the Asset Balance List which fulfil these conditions by their assetID. For each group, carry out the following task:

  1. Fetch the entry from the Asset Type List matching this assetID.
  2. Extract the genTxID field for that asset. If it is not present, do not report an error (this could be a new asset discovered from transfer metadata) and stop here.
  3. Extract the coinspark_tracker_url field from the webPageJSON field of that asset. If it is not present, do not report an error (this could be a new asset whose validity has not yet been checked) and stop here.
  4. Set the qtyChecked field for all the entries in the group to the current date/time.
  5. Send an asset tracking query to the asset tracking server specified by the coinspark_tracker_url. If coinspark_tracker_url contains more than one URL, choose one at random. The parameters of the query should be as follows:
    • Set assets to be a list containing a single item, the genTxID for this asset type.
    • Set txouts based on the list of unspent transaction outputs in this group, i.e. the unspentTxID and unspentVOut fields from the Asset Balance List entries in this group.
  6. If there was a global failure in the query response, increment qtyFailures for every entry in the group. If any of the qtyFailures values is now 1, alert the user that you could not get the balance for this asset. Stop here.
  7. For each successfully obtained qty in the query response, update the appropriate qty in the Asset Balance List, and set the corresponding qtyFailures to 0.
  8. For each partial failure in the query response, increment qtyFailures for the appropriate entry in the Asset Balance List.
  9. Redraw the displayed asset balances and asset list in the user interface if they are visible.
  10. If any of the responses contained an error other than -10001, alert the user that the asset balance could not be checked. (Error -10001 could be due to a legitimate delay in transaction propagation so need not be announced to the user.)
  11. If any of the responses contained a -10001 error and now has a corresponding qtyFailures of 120 or more, alert the user that the asset balance could not be checked. (This allows at least 10 minutes for transactions to propagate to an asset tracking server.)
  12. If any of the responses contained a -10001 error and now has a corresponding qtyFailures below 120, wait 5 seconds, then trigger this asynchronous checking of asset balances to run again.

« Previous: Bitcoin EventsNext: Interface Changes »