To get started running a Bitcoin Verde full node and block explorer on a private server, run the following commands:

Linux / Mac OS X

  1. git clone https://github.com/softwareverde/bitcoin-verde
  2. cd bitcoin-verde
  3. ./scripts/make.sh
  4. ./scripts/run-node.sh > logs/node.log &
  5. ./scripts/run-explorer.sh > logs/explorer.log &
  6. Visit http://localhost:8080/status/

Windows

Bitcoin Verde has not been well tested on Windows; please report any issues to bitcoin-verde@softwareverde.com. To run and install Bitcoin Verde on Windows, we recommend installing git-bash and following the Linux / Max OS X steps above within the git-bash terminal.

Bitcoin (Core) (BTC) is the sole group responsible for development on BTC's client. In the past, lack of a diversified development team and node implementation, have caused bugs to become a part of the protocol. BCH currently has roughly three full-node implementations (Bitcoin ABC, Bitcoin XT, Bitcoin Unlimited). However, these implementations are forked versions of the same Bitcoin (Core) reference client, which means they may share the same (undiscovered) bugs. With a diverse network of nodes, bugs in the implementation of the protocol will result in incompatible blocks, causing a temporary fork. This situation is healthy for the network in the long term, as the temporary forks will resolve over time, with the intended implementation becoming the consensus.

Bitcoin Verde is a ground-up implementation of the Bitcoin (Cash) protocol. This primary function of this project is to be a unique java implementaion of a BCH full node to diversify the BCH network's implementation.

Bitcoin Verde is also a blockchain explorer and library. Incomplete (as of v1.0.0) ambitions include a wallet module and mining-pool module (via the Stratum protocol).

Unlike the reference client, Bitcoin Verde stores the blockchain completely within a database and does not rely on dat files to serve past blocks--instead, they are inflated from the database. In this way, the database is the blockchain. The database allows for insightful queries to be run within the entire history of Bitcoin--for instance, via a query, Bitcoin Verde can report the ratio of P2PKH vs P2SH outputs, or easily report the number of transactions added to the network per a historic date.

Bitcoin Verde tracks and syncs forks; it determines the head blockchain by respecting the chain with the most Proof of Work (with a compatible ruleset). Forked/Orphaned blockchains may be visualized within the explorer. Forked blocks are stored as BlockchainSegments. These segments are stored as a Nested Set, allowing efficient queries to determine relationship among one another.

Transactions are stored with referential integrity to their spent inputs and are inserted when they are received (assuming validity and its dependant outputs have been stored). In this sense, Bitcoin Verde has an unlimited mempool size, since transactions are written to disk. Transactions attempting to spend outputs that have not yet been received are stored in a separate table until their dependent transactions have been received; in theory, this is also of unlimited size but may need to be limited in order to prevent exhaustion attacks. Since transactions are stored as they are received, they are not stored a second time once they are included in a block. Stored transactions respect the first-seen principle and not inserted into the database unless provided within a mined block.

TransactionOutput addresses are indexed as transactions are received. This functionality is required for the Explorer to be able to query the balance of addresses. With addresses indexed, it is possible to instantly sync SPV wallets in the future, once privacy concerns have been addressed and the protocol is expanded to support this functionality.

Reorgs are handled slightly differently than the reference client. Since all forked blocks are tracked and validated, and a full ledger is maintained (not just the UTXO set as in the reference client), switching to a new fork is a trivial process and does not require a reorg at all in order to validate new transactions. However, when mining, the existing mempool must be cleaned up during a reorg. This mempool reorg is handled by undoing the abandoned blocks and reapplying the blocks within the new head chain.

Nodes are also tracked within the database. In this way, Bitcoin Verde can report on the distribution of node versions and supported features.

Transactions may be trimmed from Bitcoin Verde once they are spent. This feature is experimental. With trimming enabled, spent TransactionOutputs are deleted from the database once they are a certain number of blocks old (currently 144). Currently, with this feature enabled, the Node no longer becomes a Full Node as it loses the ability to serve past blocks. Additionally, the Explorer fails to display blocks that include a transaction that has been trimmed. In the future, it possible that trimmed blocks may be stored on disk as dat files to still serve to peers; at first thought, this defeats the purpose of trimming, but still serves to reduce the disk-space footprint since these trimmed blocks will not be indexed in the database which incurs hefty space overhead due to row indexing. Without trimming enabled, a fully synced node uses 600+ GB (as of Block #562933).

Bitcoin Verde's initial sync is more complex than the reference client, which includes indexing TransactionOutput Addresses, maintaining referential constraints between transactions, and storing metadata on spent transactions. Despite a lot of effort to optimize the performance of the the initial sync, the increased complexity causes Bitcoin Verde to take significantly longer to finish synchronization compared to the refence client--about 3 to 7 days depending on hardware. Once synchronized, the Bitcoin Verde node can process upwards of 4,000 transactions per second. At 4,000 tx/s, a 32 MB block would take about 30 seconds to validate; there is still quite a bit of optimization to that must be done before Bitcoin Verde is ready to be a competitive implementation for a mining node.

Despite the storing and validating complexity drawbacks, all functionality, including networking, within Bitcoin Verde is multi-threaded. The multithreaded nature of Bitcoin Verde should allow the node process, validate, and relay more transactions per second than the reference client; furthermore, Bitcoin Verde's unlimited mempool size should help to mitigate some problems encountered during past stress-tests on the network. These claims are currently lacking data to substantiate them, and will be tested during the next network stress-test.

The project's scripts are located within scripts, its java source code is located within src, its html assets are located within www, its jni-libraries are located within jni, its default configuration is located within conf, and the built project is located within out. The sql directory contains sometimes-useful sql scripts for development and debugging. When deploying the application to a server, the out is intended to contain everything necessary for the application to run.

In general, all scripts located within any scripts directory are expected to be ran from the project root-directory. Scripts for sub-projects, such as utxo-cache, are expected to be ran from their respective sub-project root-directory.

At a minimum, the build process consists of a single script: scripts/make.sh . The make script creates an out directory, builds the application, copies dependencies, loads assets, creates a default configuration file, and creates scripts to run the application.

NOTE: Currently, the scripts/make.sh deletes the out directory, so re-running make.sh after a sync has started will cause all synchronization progress and configuration changes to be lost. It is instead recommended to run scripts/make-jar.sh when making incremental changes to the application jar.

To update the Explorer HTML/CSS/JS, run scripts/copy-www-data.sh. Changes made to the out/www directory can be made, but excluded from commits. The Explorer may not always find new resources once the server has been started, so it is recommended to restart the Explorer in between modifications.

libsecp256k1 & NativeUnspentTransactionOutputCache

By default, libsecp256k1 and NativeUnspentTransactionOutputCache prebuilt binaries are included in this project. The prebuilt libraries were built for 64-bit Linux, 64-bit OSX, and 64-bit Windows.

libsecp256k1

libsecp256k1 is an open-source C library for validating secp256k1 signatures. It is heavily optimized and provides a substantial speedup for transaction signature verification. libsecp256k1 was written by Bitcoin Core developers, Pieter Wuille and Gregory Maxwell.

If preferred, libsecp256k1 may be built from source (located at https://github.com/bitcoin-core/secp256k1) and included in Bitcoin Verde by copying the new binaries to src/main/resources/lib/libsecp256k1.[so, dylib, dll], then rebuilding the application jar.

It is not necessary to use libsecp256k1, and if the binaries are removed before building, then the application will fallback to using Bouncy Castle's implementation of secp256k1.

NativeUnspentTransactionOutputCache

NativeUnspentTransactionOutputCache is a C++ library written specifically for Bitcoin Verde. It uses cpp-btree, a B-Tree template library, written by Josh MacDonald to store Utxos in-memory with little overhead. The sourcecode for the NativeUnspentTransactionOutputCache is included in this project within jni/utxo-cache. It may be built from source via the scripts located within the jni/utxo-cache directory. The rebuilt library must be copied to src/main/resources/lib/utxocache.[so, dylib, dll].

The cpp-btree source code is included in this projected but may also be located at: http://code.google.com/p/cpp-btree/ .

It is not necessary to use the NativeUnspentTransactionOutputCache, and if the binaries are removed before building, then the application will not use any in-memory utxo caching.

Enabling SSL/TLS

Enabling SSL/TLS for the Block Explorer can be done by providing a certificate key and certificate to the explorer configuration. To generate a key, consider using the scripts/ssl/generate-certificate.sh script, or use any normal SSL script generation/signature process. In order for HttpServlet to read the certificate key, the keyfile must be in PKCS format. To convert a PEM file to a PKCS format, use the scripts/ssl/pem2pkcs.sh script. A typical location for the SSL certificates is out/ssl.

The Bitcoin Verde project has modules for varying purposes--ranging from the block-explorer module (allowing viewing and tracing transfers through the blockchain) to a simple command-line utility to generate an private-key/address.

Below are the available modules to run within Bitcoin Verde. Each module may be run either by executing their associated script or by invoking run.sh <COMMAND> <PARAMETERS> from the out directory.

ModuleCommandParametersDescription
Full Node NODE Configuration File Syncs with the Bitcoin network and validates blocks. Once fully synchronized, the node will relay transactions and new blocks to its peers.
Block Explorer EXPLORER Configuration File Starts a web-server to search blocks, transactions, and addresses. The explorer also monitors synchronization progress, server load, and peers. Additionally, the Block Explorer visualizes forks and orphaned blocks. Currently, the Block Explorer also displays this documentation.
Chain (Re)Validation VALIDATE Configuration File Iterates through the already-synced blockchain to check for any data corruption. This tool is primarily a debug module, but can improve confidence in the history of the chain in case a bug is found in the future to determine if it's been exploited without having to re-download and store the whole chain.
Repair Chain REPAIR Configuration File Block Hash(Re)Downloads the provided block from the first node within the configuration's seedNodes array, validates the block, and replaces the corrupted block with the new data. This module can repair corrupted blocks without revalidating the whole chain. This module can also be used to "undo" trimmed blocks.
Database-Only DATABASE Configuration File Starts the internal database; this module does not connect to any nodes nor does it start any of the blockchain services. The DATABASE module is primarily a debug module, but can be used to run manual queries against the state of the blockchain via ./scripts/connect-to-database.sh.
Address Generator ADDRESS Generates a private key from secure-random and outputs the hex-encoded private key, its public key, and compressed and uncompressed addresses.
Test-Block Miner MINER Previous Block Hash Bitcoin Address CPU Thread Count GPU Thread CountCreates a block based off the provided previous-block-hash, with a single coinbase transaction to the address provided. The block created will satisfy the initial Bitcoin difficulty. This mode is intended to be used to generate test-blocks.

Hosting a Block Explorer

By default, the Block Explorer runs on port 8080. When hosting the Block Explorer for the public, either a reverse proxy routing port 80 to internal 8080 can be used, or the server can be configured to route 80 to 8080 via iptables. On linux, the forward-ports.sh script in the scripts directory can be run as root to configure iptables to handle this routing. Changes made to iptables are not permanent and will be lost on restart, so it may be useful to configure this command to run on startup.

Security

Security is always a vital consideration when hosting any application. Security is a cost-benefit scale between ease of use and risk. Risk is a combination of the consequence of compromise, the scale of the vulnerability, and the value incentive to an attacker. The Bitcoin Verde node and explorer do not currently hold or manage private keys which reduces the consequence of an improperly configured server, however the value any server has to an attacked is never zero. Exposing any server to the public internet always creates a target for attacks. For this reason, Bitcoin Verde should never be run as root. Never expose bitcoin private keys (or other sensitive information) to a publicly exposed server running the Bitcoin Verde Block Explorer.

The comitted node configuration is located at conf/server.conf and it copied to out/conf/server.conf at build-time. Users are expected to modify the conf file located at out/conf/server.conf.

Below is a table with each configuration property and its purpose.

ModulePropertyDefault ValueDescription
databaserootPasswordd3d4a3d0533e3e83bc16db93414afd96The root password configured for the database. This field is not necessary to exist after the initial start of the node.
databasehostnamelocalhostThe host used to connect to the database. This value is ignored unless useEmbeddedDatabase is enabled.
databaseport8336The port used to connect to the database.
databasedataDirectorydataThe name of the directory that contains the database data within the out directory.
databaseschemabitcoinThe name of the database schema used to hold all tables.
databasemaxMemoryByteCount2GBThe maximum byte count for the InnoDB buffer pool. The buffer pool size is one of the most important configurations for performance as it configures the space used to store/cache table indexes.
databaseusernamebitcoinThe username used when connecting to the database. This value may only be changed before the initial start of the node.
databasepassword81b797117e8e0233ea8fd1d46923df54The password used when connecting to the database. This value may only be changed before the initial start of the node.
databaseuseEmbeddedDatabase1When set to 1, the node will manage its own MariaDB instance. Otherwise, the node will attempt to connect to the hostname/port and manage its database at that location. In each scenario, the node will create and manage its own schema, including creating a maintenance account and user account.
bitcoinport8333The port used to listen for incoming connections from other nodes on the network.
bitcoinrpcPort8334The port used to listen for RPC commands sent to this node.
bitcoinseedNodes["btc.softwareverde.com", "bitcoinverde.org"]The seed nodes which are initially connected to on start. Currently at least one seed node is required since DNS seeding is not currently supported. Should not exceed maxPeerCount. May optionally contain a port (eg: "bitcoinverde.org:8333").
bitcoinmaxPeerCount32The maximum number of peers that the node will accept.
bitcoinmaxThreadCount4The max number of threads used to validate a block. Currently, the server will create max(maxPeerCount * 8, 256) threads for network communication; in the future this property will likely claim this label.
bitcointrustedBlockHeight391180Blocks prior to this height will not have their transactions validated.
bitcoinskipNetworking0When set, this property disables networking with other nodes.
bitcoinmaxUtxoCacheByteCount536870912The max memory used to store Unspent Transaction Outputs in memory. This properties does nothing if the NativeUnspentTransactionOutputCache library is not loaded.
bitcoinuseTransactionBloomFilter1When set, uses an internal bloom filter to maintain a filter of transactions that have already been seen, greatly reducing the time required to store a block. When enabled, this setting requires about 1GB of memory. This property is safe to be toggled on/off between restarts.
bitcointrimBlocks0Experimental feature. When enabled, spent TransactionOutputs that are older than 144 blocks will be deleted from the database. Enabling this feature disables full-node functionality and will prevent the block explorer from functioning.
bitcoincacheBlocks1Caches the serialized block on disk within the data directory. Normally blocks are reinflated from the database whenever accessed; caching the inflated block on disk greatly improves performance of large blocks when serving blocks and merkle blocks to peers. This cache increases disk-usage.
bitcoinmaxMessagesPerSecondPerNode250May be used to prevent flooding the node; requests exceeding this throttle setting are queued. 250 msg/s supports a little over 32MB blocks.
stratumport3333The external stratum protocol port.
explorerport8080The port the explorer will listen on for incoming HTTP requests. Setting to a value lower than 1024 would require the application be run as root; this is highly discouraged. Instead, consider running on a higher port and running the forward-ports script.
explorerrootDirectorywwwThe directory where the explorer will serve its HTTP content from (eg. out/www).
explorerbitcoinRpcUrllocalhostThe host the explorer will connect to the Bitvoin Verde node on.
explorerbitcoinRpcPort8334The port the explorer will connect to the Bitcoin Verde node on.
explorertlsPort4443The port the explorer will listen on for incoming HTTPS requests. Setting to a value lower than 1024 would require the application be run as root; this is highly discouraged. Instead, consider running on a higher port and running the forward-ports script.
explorertlsKeyFileThe SSL/TLS certificate private key filename. A typical value would be something like "out/ssl/certificate.key". The default value is empty; when empty, SSL/TLS is disabled on the explorer. To generate a certificate, consider looking at scripts/ssl/generate-certificate.sh. The private key file must be in PKCS format; to convert a PEM private key to a PKCS private key, use scripts/ssl/pem2pkcs.sh.
explorertlsCertificateFileThe SSL/TLS certificate filename. A typical value would be something like "out/ssl/certificate.crt". The default value is empty; when empty, SSL/TLS is disabled on the explorer.

Bitcoin Verde has an RPC protocol to control the node while its running. The protocol listens on port 8334 by default and is configurable via the bitcoin.rpcPort configuration parameter. The RPC protocol is JSON-based and loosely mimics HTTP methods, using both GET and POST to indicate mutating/write and immutable/read operations.

An example RPC invocation to shutdown the node looks like:

{
    "method": "POST",
    "query":  "SHUTDOWN"
}

An example RPC invocation to retrieve information about a transaction looks like:

{
    "method": "GET",
    "query":  "TRANSACTION",
    "parameters": {
        "hash": "917A95AADA7B17A10661CAA2EE379E05CD816E9AB9E5C7651A371909B7222812"
    }
}

The procedures Bitcoin Verde currently support are listed below:

MethodQueryParametersDescription
GETBLOCK_HEADERSblockHeight maxBlockCount=10 rawFormat=0List block headers starting after blockHeight, or the head block if not provided. Returns at most maxBlockCount headers.
GETBLOCK_HEADERblockHeight | hashReturns the blockHeader of matching hash or at blockHeight of the head chain. blockHeight is ignored if hash is provided.
GETBLOCKblockHeight | hash rawFormat=0Returns the block of matching hash or at blockHeight of the head chain. blockHeight is ignored if hash is provided. When rawFormat is set to 1 the returned block will be as hex-encoded bytes; otherwise, it is a detailed breakdown of the block as JSON.
GETTRANSACTIONhash rawFormat=0Returns the transaction by its hash. When rawFormat is set to 1 the returned transaction will be as hex-encoded bytes; otherwise, it is a detailed breakdown of the transaction as JSON.
GETBLOCK_HEIGHTReturns the current head block height and the block header height. These values can be used to determine synchronization progress, assuming block headers have finished processing.
GETSTATUSReturns the node's status, including block/header height, services' statuses, memory usage, thread-pool utiliztion, and synchronization statistics.
GETNODESReturns a list of connected peers.
GETBALANCEaddressReturns the current balance of the provided address. Keep in mind that nodes that have not completed the initial block download may not have an up-to-date balance.
GETADDRESSaddressReturns transactions that have either sent-to or were sent-from the provided address. Keep in mind that nodes that have not completed the initial block download may not have an up-to-date list.
GETBLOCKCHAINReturns forked and orphaned blockchains that the node has witnessed. Forks and orphans are fairly rare until after the initial block download has completed.
 
POSTSHUTDOWNGracefully shuts down the node.
POSTADD_NODEhost portForces the node to connect to the specified peer. Once maxPeerCount has been reached, adding a peer will eject a node from the currently connected set.
POSTBAN_NODEhostDisconnects from and bans all nodes connected at the provided ip.
POSTUNBAN_NODEhostClears all nodes resolving to the provided ip of their banned status.
POSTADD_HOOKeventsUpgrades the RPC connection to a HookConnection. The HookConnection remains open until closed by the client. The node will relay live-updates to the HookConnection based on the events it has subscribed to. The mandatory events parameter is an array of HookEvents. Currently supported HookEvent values are: NEW_BLOCK, NEW_TRANSACTION.
POSTVALIDATE_PROTOTYPE_BLOCKblockDataValidates the Block as a prototype block for mining. The prototype block is validated against the current head blockchain in its entirety except for its hash. A blockValidation object is returned in the response; the blockValidation object contains the validation error and a list of invalid transactions, if any. The invalid transactions set may only be a subset of the invalid transactions.
POSTTRANSACTIONtransactionDataQueues the Transaction for processing into the mempool. Transactions submitted via RPC are not treated differently than transactions received from peer nodes and will be validated and accepted in the order they are received. transactionData should be the deflated bytes of the Transaction in its entirety, hex-encoded.
POSTBLOCKblockDataQueues the Block for processing. Blocks submitted via RPC are not treated differently than transactions received from peer nodes and will be validated and accepted in the order they are received. transactionData should be the deflated bytes of the Block in its entirety, hex-encoded.

An example VALIDATE_PROTOTYPE_BLOCK response looks like:

{  
    "wasSuccess":       1,
    "errorMessage":     null,
    "blockValidation": {  
        "isValid":              false,
        "errorMessage":         "Block coinbase does not contain block height.",
        "invalidTransactions":  [
            "7E7337FDEA7B55BD2105AE611EAC478889AA5D321B18B5E9389666CFB85619B6"
        ]
    }
}

Architecture

Most of the node's operations are asychronous. The primary asynchronous services are the BlockDownloader, BlockHeaderDownloader, BlockchainBuilder, AddressProcessor, TransactionDownloader, and TransactionProcessor. These various services alongside the NodeManager and the JsonRpcSocketServerHandler comprise the majority of the node's functionality. Events from one service often trigger other services to wake up; for instance, completing a block download from within the BlockDownloader triggers the BlockchainBuilder to check for available blocks to process.

Three steps are taken when a block hash or header is received: the hash is queued for download within the pending_blocks table, the node_block_inventory table is updated to keep a record of which node(s) can be used to download the block, and the BlockDownloader is woken up. The BlockDownloader queries pending_blocks for any blocks that have not been downloaded; when a match is found, the BlockDownloader checks the NodeManager for nodes that have the block inventory, and requests the block. If there are blocks that can't be downloaded because there are no peers connected that have announced that block, then a BlockFinder message is broadcasted and the pending block hashes are deleted from pending_blocks.

When a block is downloaded, the BlockchainDownloader is woken up. If there is a block that has been downloaded that has its parent block processed, the BlockchainBuilder stores and validates the block. The BlockchainBuilder continues to process blocks until it runs out of available blocks; once complete, a BlockFinder message is broadcast to all peers to ensure there are no new blocks available before the service goes back to sleep.

The AddressProcessor is woken up when a new block has been stored and validated. The AddressProcessor iterates through each TransactionOutput to index Addresses for the Block Explorer. When blockTrimming is enabled, the AddressProcessor is disabled.

Similarly to how blocks are queued for download, when a new transaction is announced its hash is queued into pending_transactions. The TransactionDownloader, TransactionProcessor share the same relationship and life-cycles as the BlockDownloader and BlockchainBuilder.

Bitcoin Verde's database is a self contained MariaDB database. The database is started when the node starts and is shut down when the node shuts down. If the node crashes, the database is not always shut down with it and lives as a zombie process; in this state, the node will fail to restart until the database is killed manually (usually via a kill command).