Table of Contents
Once two DDRP nodes are connected, they can begin synchronizing blob updates with one another. Since DDRP has no global consensus mechanism, a node is considered "in-sync" when a majority of its peers have no more updates to share.
At a high level, DDRP's synchronization protocol operates as follows:
- A node receives an update notification from one or more of its peers.
- The node requests the base of the blob's Merkle tree from one or more of its peers.
- The node requests the sectors whose hashes in the tree base differ from those stored by the requesting peer.
- The node gossips the update notification to its peers.
Note that the process involves an additional step when nodes connect to the network for the first time. This process is covered in a dedicated section.
To keep track of changes to blobs, DDRP uses a timestamp-based versioning system. When a user updates their blob, they sign both the current timestamp as well as the updated blob's Merkle root. This allows nodes to reject stale updates or updates that happen too often.
Nodes receive notification of a blob update in one of two ways: from its peers via an Update
message, or locally following a CLI-initiated update.
Update
messages have the following schema. All fields MUST be set:
type
:0x04
Data:
name
:string
timestamp
:Time
merkle_root
:[32]byte
reserved
:[32]byte
signature
:Signature
The name
field represents the Handshake TLD whose blob is being updated. It MUST be set.
The timestamp
field represents the timestamp of the blob's update.
The merkle_root
field represents the blob's Merkle root post-update.
The reserved
field is reserved for future use. It SHOULD be set to all zeroes. The reserved
field is used as part of the blob signature generation process.
The signature
field represents the signature of the blob's owner over the blob's timestamp and Merkle root.
Nodes receiving an Update
message:
- MUST disconnect from nodes that send an invalid signature.
- MUST ignore
Update
messages with atimestamp
value that precedes the referenced blob'stimestamp
. - MUST begin the sector synchronization process if the
timestamp
value proceeds the referenced blob'stimestamp
. - SHOULD ignore the
Update
message if thetimestamp
value is within the one hour window following the referenced blob'stimestamp
. - MUST resolve the provided name to a DDRP key on the Handshake blockchain in order to verify the provided
signature
.
We will describe this process from the perspective of two nodes, Alice and Bob, however in practice sector synchronization SHOULD be carried out among a group of peers. We will describe multiple-peer strategies after describing the protocol itself. The protocol works as follows, assuming that Bob sent Alice the Update
message:
The first step in the synchronization process is for Alice to request a tree base from Bob by sending a TreeBaseReq
message. It is structured as follows. All fields MUST be set:
type
:0x05
Data:
name
:string
The name
field represents the Handshake TLD being synchronized.
Once Bob receives the DiffReq
message, he responds with a DiffRes
message. The DiffRes
message is structured as follows, and all fields MUST be set:
type
:0x06
Data:
name
:string
tree_base
:[256][32]byte
The name
field represents the Handshake TLD being synchronized.
The tree_base
field represents the base of the Merkle tree as described in PIP-3.
Nodes receiving the TreeBaseRes
message:
- MUST verify the
tree_base
against themerkle_root
received in theUpdate
message.
With the tree base in hand, Alice begins requesting sector data from Bob for each sector whose hash differs from the ones described in the tree base. She does this by sending SectorReq
messages with the following structure:
type
:0x07
Data:
name
:string
sector_id
:uint16
The name
field represents the Handshake TLD for whom sectors are being requested.
The sector_id
represents the ID of the sector whose data is being requested.
All fields MUST be set.
Upon receipt of Alice's SectorReq
, Bob responds with a SectorRes
message with the following structure:
type
:0x08
Data:
name
:string
sector_id
:uint16
sector
:[256]byte
The name
field represents the Handshake TLD for whom sectors are being requested.
The sector_id
field represents the ID of the sector whose data is being returned.
The sector
field represents the returned sector's data.
Nodes receiving SectorRes
messages:
- MUST verify the
sector
field against the validatedtree_base
received in theTreeBaseRes
message.
Nodes in general:
- MUST NOT send
SectorRes
messages for names for which they have no data.
Nodes MUST send Update
messages to their peers once they complete the sector synchronization process. Nodes SHOULD filter out peers that don't need the Update
message, such as those that started the sending node's synchronization process.
When a DDRP node joins the network for the first time, it executes the following protocol to bootstrap blob data:
- The node traverses the Handshake blockchain from genesis to head, and aggregates all TLDs that contain
DDRPKEY
TXT
records. - For each TLD with a
DDRPKEY
record, the node sends anUpdateReq
message to its peers. - The node's peers respond with an
Update
message that contains the information the sending node needs to begin the sector synchronization protocol. - The node begins sector synchronization as described above.
See below for how the UpdateReq
message is structured.
type
:0x0b
Data:
name
:string
The name
field represents the name for which data is being requested.