lbcd/wire
Dave Collins a59ac5b18f
multi: Rework utxoset/view to use outpoints.
This modifies the utxoset in the database and related UtxoViewpoint to
store and work with unspent transaction outputs on a per-output basis
instead of at a transaction level.  This was inspired by similar recent
changes in Bitcoin Core.

The primary motivation is to simplify the code, pave the way for a
utxo cache, and generally focus on optimizing runtime performance.

The tradeoff is that this approach does somewhat increase the size of
the serialized utxoset since it means that the transaction hash is
duplicated for each output as a part of the key and some additional
details such as whether the containing transaction is a coinbase and the
block height it was a part of are duplicated in each output.

However, in practice, the size difference isn't all that large, disk
space is relatively cheap, certainly cheaper than memory, and it is much
more important to provide more efficient runtime operation since that is
the ultimate purpose of the daemon.

While performing this conversion, it also simplifies the code to remove
the transaction version information from the utxoset as well as the
spend journal.  The logic for only serializing it under certain
circumstances is complicated and it isn't actually used anywhere aside
from the gettxout RPC where it also isn't used by anything important
either.  Consequently, this also removes the version field of the
gettxout RPC result.

The utxos in the database are automatically migrated to the new format
with this commit and it is possible to interrupt and resume the
migration process.

Finally, it also updates the tests for the new format and adds a new
function to the tests to convert the old test data to the new format for
convenience.  The data has already been converted and updated in the
commit.

An overview of the changes are as follows:

- Remove transaction version from both spent and unspent output entries
  - Update utxo serialization format to exclude the version
  - Modify the spend journal serialization format
    - The old version field is now reserved and always stores zero and
      ignores it when reading
    - This allows old entries to be used by new code without having to
      migrate the entire spend journal
  - Remove version field from gettxout RPC result
- Convert UtxoEntry to represent a specific utxo instead of a
  transaction with all remaining utxos
  - Optimize for memory usage with an eye towards a utxo cache
    - Combine details such as whether the txout was contained in a
      coinbase, is spent, and is modified into a single packed field of
      bit flags
    - Align entry fields to eliminate extra padding since ultimately
      there will be a lot of these in memory
    - Introduce a free list for serializing an outpoint to the database
      key format to significantly reduce pressure on the GC
  - Update all related functions that previously dealt with transaction
    hashes to accept outpoints instead
  - Update all callers accordingly
  - Only add individually requested outputs from the mempool when
    constructing a mempool view
- Modify the spend journal to always store the block height and coinbase
  information with every spent txout
  - Introduce code to handle fetching the missing information from
    another utxo from the same transaction in the event an old style
    entry is encountered
    - Make use of a database cursor with seek to do this much more
      efficiently than testing every possible output
- Always decompress data loaded from the database now that a utxo entry
  only consists of a specific output
- Introduce upgrade code to migrate the utxo set to the new format
  - Store versions of the utxoset and spend journal buckets
  - Allow migration process to be interrupted and resumed
- Update all tests to expect the correct encodings, remove tests that no
  longer apply, and add new ones for the new expected behavior
  - Convert old tests for the legacy utxo format deserialization code to
    test the new function that is used during upgrade
  - Update the utxostore test data and add function that was used to
    convert it
- Introduce a few new functions on UtxoViewpoint
  - AddTxOut for adding an individual txout versus all of them
  - addTxOut to handle the common code between the new AddTxOut and
    existing AddTxOuts
  - RemoveEntry for removing an individual txout
  - fetchEntryByHash for fetching any remaining utxo for a given
    transaction hash
2018-05-27 03:07:41 -05:00
..
testdata wire: Add large tx deserialize benchmark. (#678) 2016-04-25 16:51:27 -05:00
bench_test.go BIP0143+txscript: add segwit sighash, signing, and HashCache integration 2017-08-13 23:17:40 -05:00
blockheader.go wire: typo in BlockHeader PrevBlock comment 2018-02-13 13:04:12 -06:00
blockheader_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
common.go btcd/multi: fix a number of typos in comments. 2018-01-25 23:23:59 -06:00
common_test.go chainhash: Abstract hash logic to new package. (#729) 2016-08-08 14:04:33 -05:00
doc.go wire: implement feefilter message (bip0133) 2016-10-17 13:33:16 -04:00
error.go Relicense to the btcsuite developers. 2015-05-01 12:00:56 -05:00
fakemessage_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
fixedIO_test.go multi: Simplify code per gosimple linter. 2017-03-22 15:34:13 -05:00
invvect.go BIP0144+wire: introduce new segregated witness inventory types 2017-08-13 23:17:40 -05:00
invvect_test.go chainhash: Abstract hash logic to new package. (#729) 2016-08-08 14:04:33 -05:00
message.go wire: Define CFCheckpt message. 2018-05-23 16:46:15 -07:00
message_test.go wire: Define CFCheckpt message. 2018-05-23 16:46:15 -07:00
msgaddr.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgaddr_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgalert.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgalert_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgblock.go BIP0144+wire: implement witness encoding/decoding for transactions 2017-08-13 23:17:40 -05:00
msgblock_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgcfcheckpt.go multi: fix linter warnings 2018-05-23 16:46:15 -07:00
msgcfheaders.go multi: fix linter warnings 2018-05-23 16:46:15 -07:00
msgcfilter.go multi: Redefine GetCFilters to have StartHeight and StopHash. 2018-05-23 16:46:15 -07:00
msgfeefilter.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgfeefilter_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgfilteradd.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgfilteradd_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgfilterclear.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgfilterclear_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgfilterload.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgfilterload_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msggetaddr.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msggetaddr_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msggetblocks.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msggetblocks_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msggetcfcheckpt.go multi: fix linter warnings 2018-05-23 16:46:15 -07:00
msggetcfheaders.go multi: fix linter warnings 2018-05-23 16:46:15 -07:00
msggetcfilters.go multi: fix linter warnings 2018-05-23 16:46:15 -07:00
msggetdata.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msggetdata_test.go btcd/multi: fix a number of typos in comments. 2018-01-25 23:23:59 -06:00
msggetheaders.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msggetheaders_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgheaders.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgheaders_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msginv.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msginv_test.go btcd/multi: fix a number of typos in comments. 2018-01-25 23:23:59 -06:00
msgmempool.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgmempool_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgmerkleblock.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgmerkleblock_test.go btcd/multi: fix a number of typos in comments. 2018-01-25 23:23:59 -06:00
msgnotfound.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgnotfound_test.go btcd/multi: fix a number of typos in comments. 2018-01-25 23:23:59 -06:00
msgping.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgping_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgpong.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgpong_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgreject.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgreject_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgsendheaders.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgsendheaders_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgtx.go multi: Rework utxoset/view to use outpoints. 2018-05-27 03:07:41 -05:00
msgtx_test.go BIP0144+wire: implement witness encoding/decoding for transactions 2017-08-13 23:17:40 -05:00
msgverack.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgverack_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgversion.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
msgversion_test.go BIP0144+wire: add a MessageEncoding variant for serialization/deserialization 2017-08-13 23:17:40 -05:00
netaddress.go wire: Treat NetAddress more like immutable 2016-12-06 20:48:02 +01:00
netaddress_test.go wire: Change NewNetAddress to accept a *net.TCPConn. 2016-11-04 11:06:07 -05:00
protocol.go wire: update service bits for xthin, bit 5, cfilters, and segwit2x 2018-05-23 16:46:15 -07:00
protocol_test.go wire: update service bits for xthin, bit 5, cfilters, and segwit2x 2018-05-23 16:46:15 -07:00
README.md wire: update compact filter messages to match wire.Message interface 2018-05-23 16:46:15 -07:00

wire

Build Status ISC License GoDoc

Package wire implements the bitcoin wire protocol. A comprehensive suite of tests with 100% test coverage is provided to ensure proper functionality.

There is an associated blog post about the release of this package here.

This package has intentionally been designed so it can be used as a standalone package for any projects needing to interface with bitcoin peers at the wire protocol level.

Installation and Updating

$ go get -u github.com/btcsuite/btcd/wire

Bitcoin Message Overview

The bitcoin protocol consists of exchanging messages between peers. Each message is preceded by a header which identifies information about it such as which bitcoin network it is a part of, its type, how big it is, and a checksum to verify validity. All encoding and decoding of message headers is handled by this package.

To accomplish this, there is a generic interface for bitcoin messages named Message which allows messages of any type to be read, written, or passed around through channels, functions, etc. In addition, concrete implementations of most of the currently supported bitcoin messages are provided. For these supported messages, all of the details of marshalling and unmarshalling to and from the wire using bitcoin encoding are handled so the caller doesn't have to concern themselves with the specifics.

Reading Messages Example

In order to unmarshal bitcoin messages from the wire, use the ReadMessage function. It accepts any io.Reader, but typically this will be a net.Conn to a remote node running a bitcoin peer. Example syntax is:

	// Use the most recent protocol version supported by the package and the
	// main bitcoin network.
	pver := wire.ProtocolVersion
	btcnet := wire.MainNet

	// Reads and validates the next bitcoin message from conn using the
	// protocol version pver and the bitcoin network btcnet.  The returns
	// are a wire.Message, a []byte which contains the unmarshalled
	// raw payload, and a possible error.
	msg, rawPayload, err := wire.ReadMessage(conn, pver, btcnet)
	if err != nil {
		// Log and handle the error
	}

See the package documentation for details on determining the message type.

Writing Messages Example

In order to marshal bitcoin messages to the wire, use the WriteMessage function. It accepts any io.Writer, but typically this will be a net.Conn to a remote node running a bitcoin peer. Example syntax to request addresses from a remote peer is:

	// Use the most recent protocol version supported by the package and the
	// main bitcoin network.
	pver := wire.ProtocolVersion
	btcnet := wire.MainNet

	// Create a new getaddr bitcoin message.
	msg := wire.NewMsgGetAddr()

	// Writes a bitcoin message msg to conn using the protocol version
	// pver, and the bitcoin network btcnet.  The return is a possible
	// error.
	err := wire.WriteMessage(conn, msg, pver, btcnet)
	if err != nil {
		// Log and handle the error
	}

GPG Verification Key

All official release tags are signed by Conformal so users can ensure the code has not been tampered with and is coming from the btcsuite developers. To verify the signature perform the following:

  • Download the public key from the Conformal website at https://opensource.conformal.com/GIT-GPG-KEY-conformal.txt

  • Import the public key into your GPG keyring:

    gpg --import GIT-GPG-KEY-conformal.txt
    
  • Verify the release tag with the following command where TAG_NAME is a placeholder for the specific tag:

    git tag -v TAG_NAME
    

License

Package wire is licensed under the copyfree ISC License.