threefoldtecharchive / rivine

Blockchain technology for creating custom chains.
Apache License 2.0
22 stars 12 forks source link

review block structure #628

Open GlenDC opened 4 years ago

GlenDC commented 4 years ago

Since the release of the first Rivine-based chain, the Threefold Chain (tfchain in short) the block structure of such chains can be seen as a structure with the following properties in the order as defined:

The BlockStakeOutputIndexes is defined by the following structure:

// BlockStakeOutputIndexes groups the block height, the transaction index and the output index to uniquely identify a blockstake output.
// These indexes and the value are required for the POBS protocol.
BlockStakeOutputIndexes struct {
     BlockHeight      BlockHeight
     TransactionIndex uint64
     OutputIndex      uint64
}

Each miner payout can be seen as a pair of a Value and an UnlockHash (the address which received the paired Value.

For the sake of this issue each transaction can be seen as an opaque binary object with the first byte indicating its version. How the object is to be decoded is defined by the chain, but not relevant for this issue.

Compared to other chains we make no difference between Header and Body. However given that you could see the first 3 properties as the header, with the next 2 being the body you could go from a conceptual concept to an implemented one. It would require at the very least one adaptation:

Besides this we might also want the following adaptations:

On top of that some chains also store a Nonce in the header. At the moment I am however not sure why this would be desired, given a Merkle Root hash together with the other properties (e.g. the parent ID) should be enough to make the header unique. If not, I would think you have an issues with your cryptographic primitives used. I might however mis something here.

In Memory we do already have a BlockHeader structure defined as follows:

// A BlockHeader, when encoded, is an 96-byte constant size field
// containing enough information to do headers-first block downloading.
// Hashing the header results in the block ID.
BlockHeader struct {
     ParentID
     BlockStakeOutputIndexes
     Timestamp
     MerkleRoot
}

This header is derived from the block structure listed earlier. As we already calculate the MerkleRoot based on the transactions, it wouldn't be hard to add it to an actually implementation used block header. Again I would propose to turn the BlockStakeOutputIndexes object into an opaque binary object linked to a version, so we can change the consensus algorithm when needed without hardcoding all these things in such a transparent manner. Further we again miss the version here.

The header is currently already transferred separately from the actual block between peers, to allow the receiving peer to decide whether or not the actual block is desired. It it is thus not unreasonable to go the extra mile here and also allow clients to actually download headers-only by default, and downloading actual blocks only when desired. That mile is however a long one.

Thus so far a proposal for new structures would be as follows:

type (
    BlockHeader struct {
        Version     byte
        ParentID    BlockID
        Settlement  []byte // find a better name
        Timestamp   Timestamp
        MerkleRoot  crypto.Hash
    }

    // Some chains also add a magic No in the front of a block when encoding,
    // to make sure during the decoding one can know for sure it is a block,
    // irrelevant on its actual version or content. Not sure about
    // if we really want this though.
    Block struct {
        Header BlockHeader
        // it is probably even better to remove the miner payouts property,
        // and turn them into a transaction (or transactions).
        MinerPayouts []MinerPayout
        Transactions []Transaction
    }
)
GlenDC commented 4 years ago

Papers such as the following one can help with going from this request for decent review towards an actual decent implementation that would allow Light clients to be the normality:

Superlight – A Permissionless, Light-client Only Blockchain with Self-Contained Proofs and BLS Signatures, by Roman Blum and Thomas Bocek from the University of Applied Sciences Rapperswil

robvanmieghem commented 4 years ago

thanks @GlenDC

On top of that some chains also store a Nonce in the header

That's because of the Proof of work, I removed that in the early rivine days when implementing the proof of blockstake.