chore: set empty hash to hash of nothing (#20775)

This commit is contained in:
Marko 2024-07-02 16:15:44 +02:00 committed by GitHub
parent 1bc857c417
commit 4e6507462e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 67 additions and 60 deletions

View File

@ -33,14 +33,11 @@ func (i *Info) Bytes() ([]byte, error) {
binary.LittleEndian.PutUint64(heightBytes, uint64(i.Height))
buf = append(buf, heightBytes...)
// TODO; permit empty hash OK for genesis block?
if len(i.Hash) == 0 {
i.Hash = make([]byte, hashSize)
}
// Encode Hash
if len(i.Hash) != hashSize {
return nil, errors.New("invalid hash size")
}
buf = append(buf, i.Hash...)
// Encode Time
@ -48,11 +45,8 @@ func (i *Info) Bytes() ([]byte, error) {
binary.LittleEndian.PutUint64(timeBytes, uint64(i.Time.Unix()))
buf = append(buf, timeBytes...)
if len(i.AppHash) == 0 {
i.AppHash = make([]byte, hashSize)
}
// Encode AppHash
if len(i.Hash) != hashSize {
if len(i.AppHash) != hashSize {
return nil, errors.New("invalid hash size")
}
buf = append(buf, i.AppHash...)

View File

@ -2,6 +2,7 @@ package cometbft
import (
"context"
"crypto/sha256"
"errors"
"fmt"
"sync/atomic"
@ -103,7 +104,7 @@ func (c *Consensus[T]) CheckTx(ctx context.Context, req *abciproto.CheckTxReques
return nil, err
}
cometResp := &abci.CheckTxResponse{
cometResp := &abciproto.CheckTxResponse{
Code: resp.Code,
GasWanted: uint64ToInt64(resp.GasWanted),
GasUsed: uint64ToInt64(resp.GasUsed),
@ -137,7 +138,7 @@ func (c *Consensus[T]) Info(ctx context.Context, _ *abciproto.InfoRequest) (*abc
return nil, err
}
return &abci.InfoResponse{
return &abciproto.InfoResponse{
Data: c.cfg.Name,
Version: c.cfg.Version,
// AppVersion: cp.GetVersion().App,
@ -226,11 +227,19 @@ func (c *Consensus[T]) InitChain(ctx context.Context, req *abciproto.InitChainRe
})
}
ci, err := c.store.LastCommitID()
if err != nil {
return nil, err
}
// populate hash with empty byte slice instead of nil
bz := sha256.Sum256([]byte{})
br := &coreappmgr.BlockRequest[T]{
Height: uint64(req.InitialHeight - 1),
Time: req.Time,
Hash: nil,
AppHash: nil,
Hash: bz[:],
AppHash: ci.Hash,
ChainId: req.ChainId,
ConsensusMessages: consMessages,
IsGenesis: true,
@ -271,7 +280,7 @@ func (c *Consensus[T]) InitChain(ctx context.Context, req *abciproto.InitChainRe
return nil, fmt.Errorf("unable to write the changeset: %w", err)
}
return &abci.InitChainResponse{
return &abciproto.InitChainResponse{
ConsensusParams: req.ConsensusParams,
Validators: validatorUpdates,
AppHash: stateRoot,
@ -317,7 +326,7 @@ func (c *Consensus[T]) PrepareProposal(
encodedTxs[i] = tx.Bytes()
}
return &abci.PrepareProposalResponse{
return &abciproto.PrepareProposalResponse{
Txs: encodedTxs,
}, nil
}
@ -350,13 +359,13 @@ func (c *Consensus[T]) ProcessProposal(
err := c.processProposalHandler(ciCtx, c.app, decodedTxs, req)
if err != nil {
c.logger.Error("failed to process proposal", "height", req.Height, "time", req.Time, "hash", fmt.Sprintf("%X", req.Hash), "err", err)
return &abci.ProcessProposalResponse{
Status: abci.PROCESS_PROPOSAL_STATUS_REJECT,
return &abciproto.ProcessProposalResponse{
Status: abciproto.PROCESS_PROPOSAL_STATUS_REJECT,
}, nil
}
return &abci.ProcessProposalResponse{
Status: abci.PROCESS_PROPOSAL_STATUS_ACCEPT,
return &abciproto.ProcessProposalResponse{
Status: abciproto.PROCESS_PROPOSAL_STATUS_ACCEPT,
}, nil
}
@ -529,7 +538,7 @@ func (c *Consensus[T]) VerifyVoteExtension(
resp, err := c.verifyVoteExt(ctx, latestStore, req)
if err != nil {
c.logger.Error("failed to verify vote extension", "height", req.Height, "err", err)
return &abci.VerifyVoteExtensionResponse{Status: abci.VERIFY_VOTE_EXTENSION_STATUS_REJECT}, nil
return &abciproto.VerifyVoteExtensionResponse{Status: abciproto.VERIFY_VOTE_EXTENSION_STATUS_REJECT}, nil
}
return resp, err
@ -565,7 +574,7 @@ func (c *Consensus[T]) ExtendVote(ctx context.Context, req *abciproto.ExtendVote
resp, err := c.extendVote(ctx, latestStore, req)
if err != nil {
c.logger.Error("failed to verify vote extension", "height", req.Height, "err", err)
return &abci.ExtendVoteResponse{}, nil
return &abciproto.ExtendVoteResponse{}, nil
}
return resp, err

View File

@ -4,6 +4,7 @@ import (
"context"
"cosmossdk.io/core/header"
"cosmossdk.io/core/store"
)
var _ header.Service = (*HeaderService)(nil)
@ -13,3 +14,42 @@ type HeaderService struct{}
func (h HeaderService) HeaderInfo(ctx context.Context) header.Info {
return ctx.(*executionContext).headerInfo
}
const headerInfoPrefix = 0x37
// setHeaderInfo sets the header info in the state to be used by queries in the future.
func (s STF[T]) setHeaderInfo(state store.WriterMap, headerInfo header.Info) error {
// TODO storing header info is too low level here, stf should be stateless.
// We should have a keeper that does this.
runtimeStore, err := state.GetWriter(Identity)
if err != nil {
return err
}
bz, err := headerInfo.Bytes()
if err != nil {
return err
}
err = runtimeStore.Set([]byte{headerInfoPrefix}, bz)
if err != nil {
return err
}
return nil
}
// getHeaderInfo gets the header info from the state. It should only be used for queries
func (s STF[T]) getHeaderInfo(state store.WriterMap) (i header.Info, err error) {
runtimeStore, err := state.GetWriter(Identity)
if err != nil {
return header.Info{}, err
}
v, err := runtimeStore.Get([]byte{headerInfoPrefix})
if err != nil {
return header.Info{}, err
}
if v == nil {
return header.Info{}, nil
}
err = i.FromBytes(v)
return i, err
}

View File

@ -421,45 +421,6 @@ func (s STF[T]) validatorUpdates(
return ctx.events, valSetUpdates, nil
}
const headerInfoPrefix = 0x37
// setHeaderInfo sets the header info in the state to be used by queries in the future.
func (s STF[T]) setHeaderInfo(state store.WriterMap, headerInfo header.Info) error {
// TODO storing header info is too low level here, stf should be stateless.
// We should have a keeper that does this.
runtimeStore, err := state.GetWriter(Identity)
if err != nil {
return err
}
bz, err := headerInfo.Bytes()
if err != nil {
return err
}
err = runtimeStore.Set([]byte{headerInfoPrefix}, bz)
if err != nil {
return err
}
return nil
}
// getHeaderInfo gets the header info from the state. It should only be used for queries
func (s STF[T]) getHeaderInfo(state store.WriterMap) (i header.Info, err error) {
runtimeStore, err := state.GetWriter(Identity)
if err != nil {
return header.Info{}, err
}
v, err := runtimeStore.Get([]byte{headerInfoPrefix})
if err != nil {
return header.Info{}, err
}
if v == nil {
return header.Info{}, nil
}
err = i.FromBytes(v)
return i, err
}
// Simulate simulates the execution of a tx on the provided state.
func (s STF[T]) Simulate(
ctx context.Context,

View File

@ -2,6 +2,7 @@ package root
import (
"bytes"
"crypto/sha256"
"errors"
"fmt"
"sync"
@ -148,8 +149,10 @@ func (s *Store) LastCommitID() (proof.CommitID, error) {
if err != nil {
return proof.CommitID{}, err
}
// if the latest version is 0, we return a CommitID with version 0 and a hash of an empty byte slice
bz := sha256.Sum256([]byte{})
return proof.CommitID{Version: latestVersion}, nil
return proof.CommitID{Version: latestVersion, Hash: bz[:]}, nil
}
// GetLatestVersion returns the latest version based on the latest internal