docs/source/peer_ledger_snapshot.md
For a peer to process transactions on a channel, it must contain the minimum ledger data necessary to endorse and validate transactions consistent with other peers on a channel. This includes the "world state", maintained in the state database, which represents the current value of all of the keys on the ledger (who owns a particular asset, for example) as of the most recently committed block. There are two ways for a peer to get a copy of the necessary ledger data.
While the first method represents a more comprehensive way of joining a channel, because of the size of established channels (which can reach many thousands of blocks), it can take a long time for peers to pull and process all the blocks already committed to the channel. Peers that join a channel this way must also store every block since the creation of the channel, increasing storage costs for an organization. Additionally, joining by snapshot will provide a peer with the latest channel configuration, which may be important if the channel configuration has changed since the genesis block. For example, the peer may need the orderer endpoints or CA certificates from the latest channel configuration before it can successfully pull blocks from the ordering service.
In this topic, we'll describe the process for joining a peer to a channel using a snapshot.
While creating a snapshot and using it to join a peer to a channel from a snapshot (also known as a "checkpoint") will take less time and saves on storage costs compared to processing and storing every block on the ledger, there are a few limitations to consider:
reset, rollback, or rebuild-dbs commands on peers that have joined a channel using a snapshot since the peer would not have all the block files required for the operations. Instead of these administrative commands, it is expected that peers that have joined a channel using a snapshot can be entirely rebuilt from the same or newer snapshots.peer.gossip.externalEndpoint so that the peer does not participate in service discovery.Snapshots can be used by organizations that already have peers on a channel or by organizations new to a channel. Whatever the use case, the process is largely the same.
The organization that will use the snapshot to join the channel will then:
If an organization that is already joined to the channel wants to join a new peer using a snapshot, it might decide to skip the process of having other organizations take snapshots and evaluate them, though it is a best practice for an organization to periodically take snapshots of all its peers and compare them to ensure the no ledger forks have occurred. In that case, the organization can take a snapshot immediately and then use the snapshot to join the new peer to the channel.
Snapshots can be used to verify that the state between peers is identical (in other words, that no ledger fork has occurred), even if no new peer will use the snapshot to join the channel.
This can be done by ensuring that the snapshot_hash in the file _snapshot_additional_metadata.json in the snapshots generated across peers is the same.
If the hashes are not identical, you can use the ledgerutil compare utility to troubleshoot which keys are different across any two snapshots and to understand when a divergence may have occurred.
For the full list of snapshot-related commands, check out peer snapshot commands.
Before taking a snapshot, it is a best practice to confirm the current ledger height by issuing a command similar to:
peer channel getinfo -c <name of channel>
You will see a response similar to:
Blockchain info: {"height":970,"currentBlockHash":"JgK9lcaPUNmFb5Mp1qe1SVMsx3o/22Ct4+n5tejcXCw=","previousBlockHash":"f8lZXoAn3gF86zrFq7L1DzW2aKuabH9Ow6SIE5Y04a4="}
In this example, the ledger height is 970.
A snapshot request can be submitted by issuing a command similar to:
peer snapshot submitrequest -c <name of channel> -b <ledger height where snapshot will be taken> --peerAddress <address of peer> --tlsRootCertFile <path to root certificate of the TLS CA>
For example:
peer snapshot submitrequest -c testchannel -b 1000 --peerAddress 127.0.0.1:22509 --tlsRootCertFile tls/cert.pem
If you give a ledger height of 0, the snapshot is taken immediately. This is useful for cases when an organization is interested in generating a snapshot that will be used by one of its own peers and does not intend to share the data with another organization. Do not take these "immediate" snapshots in cases when snapshots will be evaluated from multiple peers, as it increases the likelihood that the snapshots will be taken at different ledger heights.
If the request is successful, you will see a Snapshot request submitted successfully message.
You can list the pending snapshots by issuing a command similar to:
peer snapshot listpending -c testchannel --peerAddress 127.0.0.1:22509 --tlsRootCertFile tls/cert.pem
You will see a response similar to:
Successfully got pending snapshot requests [1000]
When a snapshot has been generated for a particular block height, the pending request for that block height will no longer appear in the list. You can also verify that a snapshot has been created successfully by looking at the peer logs.
Snapshots will be written to a directory based on the core.yaml ledger.snapshots.rootDir property. Completed snapshots are written to a subdirectory based on the channel name and block number of the snapshot: {ledger.snapshots.rootDir}/completed/{channelName}/{lastBlockNumberInSnapshot}. If the ledger.snapshots.rootDir property is not specified in the core.yaml, then the default value is {peer.fileSystemPath}/snapshots. If you expect a snapshot will be large, or you expect to share snapshots in the location that they are generated, consider setting the snapshot directory to a different volume than the peer's fileSystemPath.
To delete a snapshot request, simply exchange submitrequest with cancelrequest. For example:
peer snapshot cancelrequest -c testchannel -b 1000 --peerAddress 127.0.0.1:22509 --tlsRootCertFile tls/cert.pem
If you submit the listpending command again, the snapshot should no longer appear.
Once the peer generates a snapshot to the {ledger.snapshots.rootDir}/completed/{channelName}/{lastBlockNumberInSnapshot} directory, the peer does not use that directory for any purpose and it is safe to compress and transfer the snapshot using external tools, and to delete it when no longer needed.
As mentioned above, the completed snapshot directory contains files for the different data items listed below:
In addition, the snapshot contains two metadata files that help the data in the snapshot to be verified. This snapshot metadata file is expected to be same across snapshots of a channel for a particular height.
One of these files contains a JSON record called _snapshot_signable_metadata.json with the following fields:
channel_name: the name of the channel.last_block_number: the block height when the snapshot was taken.last_block_hash: a hash of the block at the height the snapshot was taken.previous_block_hash: a hash of the block prior to the last_block.state_db_type (the value of this field will be either CouchDB or SimpleKeyValueDB (also known as LevelDB).snapshot_files_raw_hashes, is a JSON record that contains the hashes of the files above.This metadata file is also a JSON record with the following two fields:
snapshot_hash, the hash of the file _snapshot_signable_metadata.json and can be treated as a hash of the snapshot.last_block_commit_hash, which is included if the snapshot generating peer is equipped to compute the block commit hashes.Note that the file types explained here is a superset of all of the files that might be included in a snapshot. If admins find some of these file types missing in their snapshots (for example, the collection config history) this is not mean the snapshot is incomplete. The channel might not have any collections.
When joining a channel using the genesis block, a command similar to peer channel join --blockpath mychannel.block is issued. When joining the peer to the channel using a snapshot, issue a command similar to:
peer channel joinbysnapshot --snapshotpath <path to snapshot>
To verify that the peer has joined the channel successfully, issue a command similar to:
peer channel getinfo -c <name of channel joined by snapshot>
Additionally, if the peer has not already installed a chaincode being used on the channel, do so, and then issue a query. A successful return of data indicates that the peer has successfully joined using the snapshot. You can then install all of the chaincodes being used on the channel. If the snapshot is used by a new organization, and the channel contains the definitions for the chaincodes that are defined using the new chaincode lifecycle, the new organization will need to approve the definition of these chaincodes before they can be invoked on the peer.
If you want to try out the ledger snapshotting process, you'll first need a network with a running channel. If you don't have a network, deploy the test network. This will create a network with two orgs, which both have a single peer, and an application channel.
Next, follow the Adding an Org to a Channel to add a new org to your network and application channel. When you reach the section where you are asked to Join Org3 to the Channel, select the peer you want to use to take the snapshot and follow the instructions above to take the snapshot. Then locate the snapshot on the peer and copy it somewhere else on your filesystem. Taking the snapshot at this step ensures that the new peer joins the channel using a snapshot taken after a point when its organization has already been joined to the channel.
After you have taken the snapshot and copied it, instead of issuing the peer channel join -b mychannel.block command, substitute peer channel joinbysnapshot --snapshotpath <path to snapshot> using the path to the snapshot on your filesystem.
There are a few reasons why a peer might fail to join a channel using a snapshot:
joinbysnapshot command.