mirror of
https://github.com/tendermint/tendermint.git
synced 2026-09-30 03:35:34 +00:00
backport block size fixes (#5492)
* mempool: length prefix txs when getting them from mempool (#5483) * correctly calculate evidence data size (#5482) * block: use commit sig size instead of vote size (#5490) * tx: reduce function to one parameter (#5493)
This commit is contained in:
+26
-33
@@ -277,7 +277,7 @@ func MaxDataBytes(maxBytes, evidenceBytes int64, valsCount int) int64 {
|
||||
maxDataBytes := maxBytes -
|
||||
MaxOverheadForBlock -
|
||||
MaxHeaderBytes -
|
||||
int64(valsCount)*MaxVoteBytes -
|
||||
MaxCommitBytes(valsCount) -
|
||||
evidenceBytes
|
||||
|
||||
if maxDataBytes < 0 {
|
||||
@@ -289,7 +289,6 @@ func MaxDataBytes(maxBytes, evidenceBytes int64, valsCount int) int64 {
|
||||
}
|
||||
|
||||
return maxDataBytes
|
||||
|
||||
}
|
||||
|
||||
// MaxDataBytesNoEvidence returns the maximum size of block's data when
|
||||
@@ -301,7 +300,7 @@ func MaxDataBytesNoEvidence(maxBytes int64, valsCount int) int64 {
|
||||
maxDataBytes := maxBytes -
|
||||
MaxOverheadForBlock -
|
||||
MaxHeaderBytes -
|
||||
int64(valsCount)*MaxVoteBytes
|
||||
MaxCommitBytes(valsCount)
|
||||
|
||||
if maxDataBytes < 0 {
|
||||
panic(fmt.Sprintf(
|
||||
@@ -581,6 +580,14 @@ const (
|
||||
BlockIDFlagNil
|
||||
)
|
||||
|
||||
const (
|
||||
// Max size of commit without any commitSigs -> 82 for BlockID, 8 for Height, 4 for Round.
|
||||
MaxCommitOverheadBytes int64 = 94
|
||||
// Commit sig size is made up of 32 bytes for the signature, 20 bytes for the address,
|
||||
// 1 byte for the flag and 14 bytes for the timestamp
|
||||
MaxCommitSigBytes int64 = 77
|
||||
)
|
||||
|
||||
// CommitSig is a part of the Vote included in a Commit.
|
||||
type CommitSig struct {
|
||||
BlockIDFlag BlockIDFlag `json:"block_id_flag"`
|
||||
@@ -599,9 +606,10 @@ func NewCommitSigForBlock(signature []byte, valAddr Address, ts time.Time) Commi
|
||||
}
|
||||
}
|
||||
|
||||
// ForBlock returns true if CommitSig is for the block.
|
||||
func (cs CommitSig) ForBlock() bool {
|
||||
return cs.BlockIDFlag == BlockIDFlagCommit
|
||||
func MaxCommitBytes(valCount int) int64 {
|
||||
// From the repeated commit sig field
|
||||
var protoEncodingOverhead int64 = 2
|
||||
return MaxCommitOverheadBytes + ((MaxCommitSigBytes + protoEncodingOverhead) * int64(valCount))
|
||||
}
|
||||
|
||||
// NewCommitSigAbsent returns new CommitSig with BlockIDFlagAbsent. Other
|
||||
@@ -612,6 +620,11 @@ func NewCommitSigAbsent() CommitSig {
|
||||
}
|
||||
}
|
||||
|
||||
// ForBlock returns true if CommitSig is for the block.
|
||||
func (cs CommitSig) ForBlock() bool {
|
||||
return cs.BlockIDFlag == BlockIDFlagCommit
|
||||
}
|
||||
|
||||
// Absent returns true if CommitSig is absent.
|
||||
func (cs CommitSig) Absent() bool {
|
||||
return cs.BlockIDFlag == BlockIDFlagAbsent
|
||||
@@ -935,10 +948,7 @@ func (commit *Commit) ToProto() *tmproto.Commit {
|
||||
c.Height = commit.Height
|
||||
c.Round = commit.Round
|
||||
c.BlockID = commit.BlockID.ToProto()
|
||||
if commit.hash != nil {
|
||||
c.Hash = commit.hash
|
||||
}
|
||||
c.BitArray = commit.bitArray.ToProto()
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -950,8 +960,7 @@ func CommitFromProto(cp *tmproto.Commit) (*Commit, error) {
|
||||
}
|
||||
|
||||
var (
|
||||
commit = new(Commit)
|
||||
bitArray *bits.BitArray
|
||||
commit = new(Commit)
|
||||
)
|
||||
|
||||
bi, err := BlockIDFromProto(&cp.BlockID)
|
||||
@@ -959,8 +968,6 @@ func CommitFromProto(cp *tmproto.Commit) (*Commit, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bitArray.FromProto(cp.BitArray)
|
||||
|
||||
sigs := make([]CommitSig, len(cp.Signatures))
|
||||
for i := range cp.Signatures {
|
||||
if err := sigs[i].FromProto(cp.Signatures[i]); err != nil {
|
||||
@@ -972,8 +979,6 @@ func CommitFromProto(cp *tmproto.Commit) (*Commit, error) {
|
||||
commit.Height = cp.Height
|
||||
commit.Round = cp.Round
|
||||
commit.BlockID = *bi
|
||||
commit.hash = cp.Hash
|
||||
commit.bitArray = bitArray
|
||||
|
||||
return commit, commit.ValidateBasic()
|
||||
}
|
||||
@@ -1035,10 +1040,6 @@ func (data *Data) ToProto() tmproto.Data {
|
||||
tp.Txs = txBzs
|
||||
}
|
||||
|
||||
if data.hash != nil {
|
||||
tp.Hash = data.hash
|
||||
}
|
||||
|
||||
return *tp
|
||||
}
|
||||
|
||||
@@ -1060,8 +1061,6 @@ func DataFromProto(dp *tmproto.Data) (Data, error) {
|
||||
data.Txs = Txs{}
|
||||
}
|
||||
|
||||
data.hash = dp.Hash
|
||||
|
||||
return *data, nil
|
||||
}
|
||||
|
||||
@@ -1087,13 +1086,11 @@ func (data *EvidenceData) Hash() tmbytes.HexBytes {
|
||||
// ByteSize returns the total byte size of all the evidence
|
||||
func (data *EvidenceData) ByteSize() int64 {
|
||||
if data.byteSize == 0 && len(data.Evidence) != 0 {
|
||||
for _, ev := range data.Evidence {
|
||||
pb, err := EvidenceToProto(ev)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
data.byteSize += int64(pb.Size())
|
||||
pb, err := data.ToProto()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
data.byteSize = int64(pb.Size())
|
||||
}
|
||||
return data.byteSize
|
||||
}
|
||||
@@ -1135,10 +1132,6 @@ func (data *EvidenceData) ToProto() (*tmproto.EvidenceData, error) {
|
||||
}
|
||||
evi.Evidence = eviBzs
|
||||
|
||||
if data.hash != nil {
|
||||
evi.Hash = data.hash
|
||||
}
|
||||
|
||||
return evi, nil
|
||||
}
|
||||
|
||||
@@ -1155,9 +1148,9 @@ func (data *EvidenceData) FromProto(eviData *tmproto.EvidenceData) error {
|
||||
return err
|
||||
}
|
||||
eviBzs[i] = evi
|
||||
data.byteSize += int64(eviData.Evidence[i].Size())
|
||||
}
|
||||
data.Evidence = eviBzs
|
||||
data.byteSize = int64(eviData.Size())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+62
-8
@@ -257,6 +257,62 @@ func TestCommitValidateBasic(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaxCommitSigBytes(t *testing.T) {
|
||||
// time is varint encoded so need to pick the max.
|
||||
// year int, month Month, day, hour, min, sec, nsec int, loc *Location
|
||||
timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC)
|
||||
|
||||
cs := &CommitSig{
|
||||
BlockIDFlag: BlockIDFlagNil,
|
||||
ValidatorAddress: crypto.AddressHash([]byte("validator_address")),
|
||||
Timestamp: timestamp,
|
||||
Signature: tmhash.Sum([]byte("signature")),
|
||||
}
|
||||
|
||||
pb := cs.ToProto()
|
||||
|
||||
assert.EqualValues(t, MaxCommitSigBytes, pb.Size())
|
||||
}
|
||||
|
||||
func TestMaxCommitBytes(t *testing.T) {
|
||||
timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC)
|
||||
|
||||
cs := CommitSig{
|
||||
BlockIDFlag: BlockIDFlagNil,
|
||||
ValidatorAddress: crypto.AddressHash([]byte("validator_address")),
|
||||
Timestamp: timestamp,
|
||||
Signature: tmhash.Sum([]byte("signature")),
|
||||
}
|
||||
|
||||
// check size with a single commit
|
||||
commit := &Commit{
|
||||
Height: math.MaxInt64,
|
||||
Round: math.MaxInt32,
|
||||
BlockID: BlockID{
|
||||
Hash: tmhash.Sum([]byte("blockID_hash")),
|
||||
PartSetHeader: PartSetHeader{
|
||||
Total: math.MaxInt32,
|
||||
Hash: tmhash.Sum([]byte("blockID_part_set_header_hash")),
|
||||
},
|
||||
},
|
||||
Signatures: []CommitSig{cs},
|
||||
}
|
||||
|
||||
pb := commit.ToProto()
|
||||
|
||||
assert.EqualValues(t, MaxCommitBytes(1), int64(pb.Size()))
|
||||
|
||||
// check the upper bound of the commit size
|
||||
for i := 1; i < MaxVotesCount; i++ {
|
||||
commit.Signatures = append(commit.Signatures, cs)
|
||||
}
|
||||
|
||||
pb = commit.ToProto()
|
||||
|
||||
assert.EqualValues(t, MaxCommitBytes(MaxVotesCount), int64(pb.Size()))
|
||||
|
||||
}
|
||||
|
||||
func TestHeaderHash(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
@@ -407,9 +463,9 @@ func TestBlockMaxDataBytes(t *testing.T) {
|
||||
}{
|
||||
0: {-10, 1, 0, true, 0},
|
||||
1: {10, 1, 0, true, 0},
|
||||
2: {844, 1, 0, true, 0},
|
||||
3: {846, 1, 0, false, 0},
|
||||
4: {847, 1, 0, false, 1},
|
||||
2: {809, 1, 0, true, 0},
|
||||
3: {810, 1, 0, false, 0},
|
||||
4: {811, 1, 0, false, 1},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
@@ -436,9 +492,9 @@ func TestBlockMaxDataBytesNoEvidence(t *testing.T) {
|
||||
}{
|
||||
0: {-10, 1, true, 0},
|
||||
1: {10, 1, true, 0},
|
||||
2: {845, 1, true, 0},
|
||||
3: {846, 1, false, 0},
|
||||
4: {847, 1, false, 1},
|
||||
2: {809, 1, true, 0},
|
||||
3: {810, 1, false, 0},
|
||||
4: {811, 1, false, 1},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
@@ -628,9 +684,7 @@ func TestBlockProtoBuf(t *testing.T) {
|
||||
|
||||
func TestDataProtoBuf(t *testing.T) {
|
||||
data := &Data{Txs: Txs{Tx([]byte{1}), Tx([]byte{2}), Tx([]byte{3})}}
|
||||
_ = data.Hash()
|
||||
data2 := &Data{Txs: Txs{}}
|
||||
_ = data2.Hash()
|
||||
testCases := []struct {
|
||||
msg string
|
||||
data1 *Data
|
||||
|
||||
@@ -137,3 +137,11 @@ func TxProofFromProto(pb tmproto.TxProof) (TxProof, error) {
|
||||
|
||||
return pbtp, nil
|
||||
}
|
||||
|
||||
// ComputeProtoSizeForTxs wraps the transactions in tmproto.Data{} and calculates the size.
|
||||
// https://developers.google.com/protocol-buffers/docs/encoding
|
||||
func ComputeProtoSizeForTxs(txs []Tx) int64 {
|
||||
data := Data{Txs: txs}
|
||||
pdData := data.ToProto()
|
||||
return int64(pdData.Size())
|
||||
}
|
||||
|
||||
+1
-3
@@ -13,9 +13,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// MaxVoteBytes is a maximum vote size (including amino overhead).
|
||||
MaxVoteBytes int64 = 209
|
||||
nilVoteStr string = "nil-Vote"
|
||||
nilVoteStr string = "nil-Vote"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -218,38 +217,6 @@ func TestVoteVerify(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaxVoteBytes(t *testing.T) {
|
||||
// time is varint encoded so need to pick the max.
|
||||
// year int, month Month, day, hour, min, sec, nsec int, loc *Location
|
||||
timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC)
|
||||
|
||||
vote := &Vote{
|
||||
ValidatorAddress: crypto.AddressHash([]byte("validator_address")),
|
||||
ValidatorIndex: math.MaxInt32,
|
||||
Height: math.MaxInt64,
|
||||
Round: math.MaxInt32,
|
||||
Timestamp: timestamp,
|
||||
Type: tmproto.PrevoteType,
|
||||
BlockID: BlockID{
|
||||
Hash: tmhash.Sum([]byte("blockID_hash")),
|
||||
PartSetHeader: PartSetHeader{
|
||||
Total: math.MaxInt32,
|
||||
Hash: tmhash.Sum([]byte("blockID_part_set_header_hash")),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
v := vote.ToProto()
|
||||
privVal := NewMockPV()
|
||||
err := privVal.SignVote("test_chain_id", v)
|
||||
require.NoError(t, err)
|
||||
|
||||
bz, err := proto.Marshal(v)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.EqualValues(t, MaxVoteBytes, len(bz))
|
||||
}
|
||||
|
||||
func TestVoteString(t *testing.T) {
|
||||
str := examplePrecommit().String()
|
||||
expected := `Vote{56789:6AF1F4111082 12345/02/SIGNED_MSG_TYPE_PRECOMMIT(Precommit) 8B01023386C3 000000000000 @ 2017-12-25T03:00:01.234Z}` //nolint:lll //ignore line length for tests
|
||||
|
||||
Reference in New Issue
Block a user