Skip to content

Commit

Permalink
feat!: sync with mainline ABCI (#1003)
Browse files Browse the repository at this point in the history
Use the same PrepareProposal and ProcessProposal methods as is in CometBFT
  • Loading branch information
cmwaters committed Jul 20, 2023
1 parent a1b07a1 commit 2c6cde4
Show file tree
Hide file tree
Showing 33 changed files with 1,854 additions and 770 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

celestia-core is a fork of [cometbft/cometbft](https://github.com/cometbft/cometbft), an implementation of the Tendermint protocol, with the following changes:

1. Early adoption of the ABCI++ methods: `PrepareProposal` and `ProcessProposal` because they haven't yet landed in a CometBFT release.
1. Modifications to how `DataHash` in the block header is determined. In CometBFT, `DataHash` is based on the transactions included in a block. In Celestia, block data (including transactions) are erasure coded into a data square to enable data availability sampling. In order for the header to contain a commitment to this data square, `DataHash` was modified to be the Merkle root of the row and column roots of the erasure coded data square. See [ADR 008](https://github.com/celestiaorg/celestia-core/blob/v0.34.x-celestia/docs/celestia-architecture/adr-008-updating-to-tendermint-v0.35.x.md?plain=1#L20) for the motivation or [celestia-app/pkg/da/data_availability_header.go](https://github.com/celestiaorg/celestia-app/blob/2f89956b22c4c3cfdec19b3b8601095af6f69804/pkg/da/data_availability_header.go) for the implementation. Note on the implementation: celestia-app computes the hash in prepare_proposal and returns it to CometBFT via [`blockData.Hash`](https://github.com/celestiaorg/celestia-app/blob/5bbdac2d3f46662a34b2111602b8f964d6e6fba5/app/prepare_proposal.go#L78) so a modification to celestia-core isn't strictly necessary but [comments](https://github.com/celestiaorg/celestia-core/blob/2ec23f804691afc196d0104616e6c880d4c1ca41/types/block.go#L1041-L1042) were added.
1. Modifications to how `DataHash` in the block header is determined. In CometBFT, `DataHash` is based on the transactions included in a block. In Celestia, block data (including transactions) are erasure coded into a data square to enable data availability sampling. In order for the header to contain a commitment to this data square, `DataHash` was modified to be the Merkle root of the row and column roots of the erasure coded data square. See [ADR 008](https://github.com/celestiaorg/celestia-core/blob/v0.34.x-celestia/docs/celestia-architecture/adr-008-updating-to-tendermint-v0.35.x.md?plain=1#L20) for the motivation or [celestia-app/pkg/da/data_availability_header.go](https://github.com/celestiaorg/celestia-app/blob/2f89956b22c4c3cfdec19b3b8601095af6f69804/pkg/da/data_availability_header.go) for the implementation. The `DataHash` is computed by the application in `PrepareProposal` and returned to `CometBFT` as the second to last transaction. The last transaction is the big endian encoded uint64 of the square size. The `SquareSize` is included in the modified `Data` struct that is gossiped to peers. Similarly `CometBFT` passes the `DataHash` as the second to last tx and the `SquareSize` as the final transaction in `ProcessProposal`.
2. A content-addressable transaction (CAT) pool was implemented using the `Mempool` interface to reduce the duplication and thus bandwidth of peers sending transactions to one another. The specification can be found [here](./mempool/cat/spec.md).


See [./docs/celestia-architecture](./docs/celestia-architecture/) for architecture decision records (ADRs) on Celestia modifications.
Expand Down
4 changes: 2 additions & 2 deletions abci/example/kvstore/persistent_kvstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func (app *PersistentKVStoreApplication) BeginBlock(req types.RequestBeginBlock)

// Punish validators who committed equivocation.
for _, ev := range req.ByzantineValidators {
if ev.Type == types.EvidenceType_DUPLICATE_VOTE {
if ev.Type == types.MisbehaviorType_DUPLICATE_VOTE {
addr := string(ev.Validator.Address)
if pubKey, ok := app.valAddrToPubKeyMap[addr]; ok {
app.updateValidator(types.ValidatorUpdate{
Expand Down Expand Up @@ -180,7 +180,7 @@ func (app *PersistentKVStoreApplication) PrepareProposal(

func (app *PersistentKVStoreApplication) ProcessProposal(
req types.RequestProcessProposal) types.ResponseProcessProposal {
return types.ResponseProcessProposal{Result: types.ResponseProcessProposal_ACCEPT}
return types.ResponseProcessProposal{Status: types.ResponseProcessProposal_ACCEPT}
}

//---------------------------------------------
Expand Down
13 changes: 10 additions & 3 deletions abci/types/application.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package types

import (
context "golang.org/x/net/context"
"context"
"encoding/binary"

"github.com/tendermint/tendermint/crypto/tmhash"
)

// Application is an interface that enables any finite, deterministic state machine
Expand Down Expand Up @@ -98,11 +101,15 @@ func (BaseApplication) ApplySnapshotChunk(req RequestApplySnapshotChunk) Respons
}

func (BaseApplication) PrepareProposal(req RequestPrepareProposal) ResponsePrepareProposal {
return ResponsePrepareProposal{BlockData: req.BlockData}
// we use placeholder values for the hash and square size
squareSizeBytes := make([]byte, 8)
binary.BigEndian.PutUint64(squareSizeBytes, 0)
req.Txs = append(req.Txs, tmhash.Sum(nil), squareSizeBytes)
return ResponsePrepareProposal{Txs: req.Txs}
}

func (BaseApplication) ProcessProposal(req RequestProcessProposal) ResponseProcessProposal {
return ResponseProcessProposal{Result: ResponseProcessProposal_ACCEPT}
return ResponseProcessProposal{Status: ResponseProcessProposal_ACCEPT}
}

//-------------------------------------------------------
Expand Down
13 changes: 7 additions & 6 deletions abci/types/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,20 @@ func (r ResponseQuery) IsErr() bool {
return r.Code != CodeTypeOK
}

// IsUnknown returns true if Code is Unknown
// IsUnknown returns true if this ResponseProcessProposal status is unknown

func (r ResponseProcessProposal) IsUnknown() bool {
return r.Result == ResponseProcessProposal_UNKNOWN
return r.Status == ResponseProcessProposal_UNKNOWN
}

// IsOK returns true if Code is OK
func (r ResponseProcessProposal) IsOK() bool {
return r.Result == ResponseProcessProposal_ACCEPT
// IsAccepted returns true if this ResponseProcessProposal was accepted
func (r ResponseProcessProposal) IsAccepted() bool {
return r.Status == ResponseProcessProposal_ACCEPT
}

// IsRejected returns true if this ResponseProcessProposal was rejected
func (r ResponseProcessProposal) IsRejected() bool {
return r.Result == ResponseProcessProposal_REJECT
return r.Status == ResponseProcessProposal_REJECT
}

//---------------------------------------------------------------------------
Expand Down
Loading

0 comments on commit 2c6cde4

Please sign in to comment.