From 16227594ef4ab384504b1f5c2f01dc94df58cff8 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 26 Dec 2017 16:33:42 -0500 Subject: [PATCH] notes about block 1 --- docs/specification/new-spec/blockchain.md | 30 ++++++++++++++++++++--- docs/specification/new-spec/encoding.md | 10 ++++++++ docs/specification/new-spec/wire.go | 3 +++ 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/docs/specification/new-spec/blockchain.md b/docs/specification/new-spec/blockchain.md index 64e31a94f..c99fc639b 100644 --- a/docs/specification/new-spec/blockchain.md +++ b/docs/specification/new-spec/blockchain.md @@ -5,7 +5,7 @@ Here we describe the data structures in the Tendermint blockchain and the rules # Data Structures The Tendermint blockchains consists of a short list of basic data types: -`Block`, `Header`, `Vote`, `BlockID`, and `Signature`. +`Block`, `Header`, `Vote`, `BlockID`, `Signature`, and `Evidence`. ## Block @@ -135,6 +135,10 @@ where `Signature` is the DER encoded signature, ie: 0x30 <0x02> 0x2 . ``` +## Evidence + +TODO + # Validation Here we describe the validation rules for every element in block. @@ -171,6 +175,8 @@ block.Header.Height > 0 block.Header.Height == prevBlock.Header.Height + 1 ``` +The height is an incrementing integer. The first block has `block.Header.Height == 1`. + ### Time The median of the timestamps of the valid votes in the block.LastCommit. @@ -202,14 +208,18 @@ block.Header.LastCommitHash == SimpleMerkleRoot(block.LastCommit) Simple Merkle root of the votes included in the block. These are the votes that committed the previous block. +The first block has `block.Header.LastCommitHash == []byte{}` + ### TotalTxs ``` -block.Header.TotalTxs == prevBlock.Header.TotalTxs + block.header.NumTxs +block.Header.TotalTxs == prevBlock.Header.TotalTxs + block.Header.NumTxs ``` The cumulative sum of all transactions included in this blockchain. +The first block has `block.Header.TotalTxs = block.Header.NumberTxs`. + ### LastBlockID ``` @@ -224,6 +234,8 @@ block.HeaderLastBlockID == BlockID{ Previous block's BlockID. Note it depends on the ConsensusParams, which are held in the `state` and may be updated by the application. +The first block has `block.Header.LastBlockID == BlockID{}`. + ### ResultsHash ``` @@ -232,6 +244,8 @@ block.ResultsHash == SimpleMerkleRoot(app.Results) Simple Merkle root of the results of the transactions in the previous block. +The first block has `block.Header.ResultsHash == []byte{}`. + ### AppHash ``` @@ -240,6 +254,8 @@ block.AppHash == app.AppHash Arbitrary byte array returned by the application after executing and commiting the previous block. +The first block has `block.Header.AppHash == []byte{}`. + ### ValidatorsHash ``` @@ -248,7 +264,7 @@ block.ValidatorsHash == SimpleMerkleRoot(state.Validators) Simple Merkle root of the current validator set that is committing the block. This can be used to validate the `LastCommit` included in the next block. -May be updated by the applicatoin. +May be updated by the application. ### ConsensusParamsHash @@ -261,9 +277,15 @@ May be updated by the application. ### Proposer +``` +block.Header.Proposer in state.Validators +``` + Original proposer of the block. -TODO +NOTE: this field can only be further verified by real-time participants in the consensus. +This is because the same block can be proposed in multiple rounds for the same height +and we do not track the initial round the block was proposed. ### EvidenceHash diff --git a/docs/specification/new-spec/encoding.md b/docs/specification/new-spec/encoding.md index bfbeb206b..584b0253e 100644 --- a/docs/specification/new-spec/encoding.md +++ b/docs/specification/new-spec/encoding.md @@ -31,6 +31,8 @@ The length-prefix consists of a single byte and corresponds to the length of the Negative integers are encoded by flipping the leading bit of the length-prefix to a `1`. +Zero is encoded as `0x00`. It is not length-prefixed. + Examples: @@ -40,6 +42,8 @@ encode(uint(70000)) == [0x03, 0x01, 0x11, 0x70] encode(int(-6)) == [0xF1, 0x06] encode(int(-70000)) == [0xF3, 0x01, 0x11, 0x70] + +encode(int(0)) == [0x00] ``` ### Strings @@ -47,9 +51,12 @@ encode(int(-70000)) == [0xF3, 0x01, 0x11, 0x70] An encoded string is a length prefix followed by the underlying bytes of the string. The length-prefix is itself encoded as an `int`. +The empty string is encoded as `0x00`. It is not length-prefixed. + Examples: ``` +encode("") == [0x00] encode("a") == [0x01, 0x01, 0x61] encode("hello") == [0x01, 0x05, 0x68, 0x65, 0x6C, 0x6C, 0x6F] encode("¥") == [0x01, 0x02, 0xC2, 0xA5] @@ -74,9 +81,12 @@ encode([2]string{"abc", "efg"}) == [0x01, 0x03, 0x61, 0x62, 0x63, 0x01, 0x03, 0x An encoded variable-length array is a length prefix followed by the concatenation of the encoding of its elements. The length-prefix is itself encoded as an `int`. +An empty slice is encoded as `0x00`. It is not length-prefixed. + Examples: ``` +encode([]int8{}) == [0x00] encode([]int8{1, 2, 3, 4}) == [0x01, 0x04, 0x01, 0x02, 0x03, 0x04] encode([]int16{1, 2, 3, 4}) == [0x01, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04] encode([]int{1, 2, 3, 4}) == [0x01, 0x04, 0x01, 0x01, 0x01, 0x02, 0x01, 0x03, 0x01, 0x4] diff --git a/docs/specification/new-spec/wire.go b/docs/specification/new-spec/wire.go index 1f8e412ff..af76f3669 100644 --- a/docs/specification/new-spec/wire.go +++ b/docs/specification/new-spec/wire.go @@ -16,9 +16,11 @@ func main() { Break() encode(uint(6)) encode(uint(70000)) + encode(int(0)) encode(int(-6)) encode(int(-70000)) Break() + encode("") encode("a") encode("hello") encode("¥") @@ -28,6 +30,7 @@ func main() { encode([4]int{1, 2, 3, 4}) encode([2]string{"abc", "efg"}) Break() + encode([]int8{}) encode([]int8{1, 2, 3, 4}) encode([]int16{1, 2, 3, 4}) encode([]int{1, 2, 3, 4})