Skip to content
killerstorm edited this page Sep 4, 2012 · 4 revisions

Overview

In this Bitcoin coloring implementation we aim to assign a color label to each transaction. It's worth noting that more fine-grained coloring is possible (each txn output can have its own color), but it is only required for advanced use such as secure exchange via blockchain.

So in this proof-of-concept implementation we choose to follow a simple approach of one color per transaction.

The general rule of coloring is that transaction has color X if all its inputs come from transactions with color X, but there is a number of extra rules:

  • Coinbase transactions (which have no inputs) are of a generic color (called COLOR_DEFAULT = 0 in code)
  • We explicitly assign color to some transactions in a configuration file. Those transactions are called genesis transactions and they semantically represent initial issuance of private currency/asset.
  • If transaction has inputs of different colors it is of 'mixed' color (COLOR_MIXED = -1). Mixed color is semantically same as default, we introduce it only for debugging purposes.

These rules can be extended later to accommodate txn fees and exchange, but we start with these simple rules in a proof-of-concept.

Color representation

In this implementation color is represented with an integer: COLOR_DEFAULT is 0, COLOR_MIXED is -1, COLOR_UNKNOWN is -2 (only used internally). The rest of numbers can be used for user-defined colors. (I.e. defined in configuration.)

Integers are less than ideal choice for colors, hashes would be better, but I'm using integers for simplicity of debugging. It can be changed later.

TxDB

We need to store colors somewhere to avoid re-computing them each time. We'll store color for each transaction in CTxDB 'index'. (If it creates a performance problem later we can store colors only selectively, e.g. for unspent transactions only.). Methods which read/store colors are:

int CTxDB::ReadColor(uint256 txhash);
bool CTxDB::WriteColor(uint256 txhash, int color);

It's worth noting that WriteColor does nothing if DB is open in read-only mode, that's because this DB is just a cache and we can re-compute color at any time.

Transaction Coloring

Actual methods which compute colors are implemented in CTransaction:

int CTransaction::GetColor(CTxDB& txdb) const 
int CTransaction::GetPredefinedColor() const
int CTransaction::ComputeColor(CTxDB& txdb) const
int CTransaction::ComputeColor(CTxDB& txdb, MapPrevTx& inputs) const

GetColor is a method which returns transaction's color, it can be called whenever some part of client wants to know a color of a certain transaction. This method is public and rest of methods listed here should be in theory private. GetColor itself finds transaction color by performing following operations (in this order):

  1. GetPredefinedColor() returns color for transactions which are colored via configuration color or get generic color by being coinbase transactions.
  2. then it calls CTxDB's ReadColor to find cached color value.
  3. If value is not cached ComputeColor(CTxDB& txdb) is called to compute color from colors of inputs.
  4. ComputeColor(CTxDB& txdb) fetches inputs and calls ComputeColor(CTxDB& txdb, MapPrevTx& inputs)
  5. ComputeColor(CTxDB& txdb, MapPrevTx& inputs) computes color via colors of inputs and stores cached value in database

ComputeColor(CTxDB& txdb, MapPrevTx& inputs) is also called from CBlock::ConnectBlock, block already has fetched inputs so this works faster.

Genesis transactions are defined right in code, in GetPredefinedColor() method. Later this can be moved into a separate configuration file.

Wallet integration

I assume that user has multiple wallets with one wallet per color. Thus wallet integration is limited to not accepting transactions which do not match wallet's color.

This is enough for a proof-of-concept. I.e. a merchant which wants to accept only "green bitcoins" won't be fooled with generic bitcoins: he will see only "green bitcoins" in his wallet and he will send only "green bitcoins" to an exchange. So it works, sort of. But we really probably want more flexible wallets. This requires more coding, though.

So wallet needs to know color of transactions in one way or another, and so we need to pass CTxDB to it. This is why some code restructuring was necessary. If we create CTxDB in AddToWalletIfInvolvingMe while there is another CTxDB which accesses same transactions it might cause a deadlock due to overlapping access.

Current version can work with one wallet at a time, color of wallet is chosen at startup from parameters(e.g. ./bitcoind -walletcolor=1 -walletname=wallet1.dat would open a wallet for color 1).

Clone this wiki locally