github.com/okex/exchain@v1.8.0/libs/tendermint/types/block.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 "io" 8 "strings" 9 "sync" 10 "time" 11 12 gogotypes "github.com/gogo/protobuf/types" 13 "github.com/okex/exchain/libs/system/trace" 14 "github.com/okex/exchain/libs/tendermint/libs/compress" 15 tmtime "github.com/okex/exchain/libs/tendermint/types/time" 16 17 "github.com/tendermint/go-amino" 18 19 "github.com/pkg/errors" 20 21 "github.com/okex/exchain/libs/tendermint/crypto" 22 "github.com/okex/exchain/libs/tendermint/crypto/merkle" 23 "github.com/okex/exchain/libs/tendermint/crypto/tmhash" 24 "github.com/okex/exchain/libs/tendermint/libs/bits" 25 tmbytes "github.com/okex/exchain/libs/tendermint/libs/bytes" 26 tmmath "github.com/okex/exchain/libs/tendermint/libs/math" 27 tmproto "github.com/okex/exchain/libs/tendermint/proto/types" 28 tmversion "github.com/okex/exchain/libs/tendermint/proto/version" 29 "github.com/okex/exchain/libs/tendermint/version" 30 ) 31 32 const ( 33 // MaxHeaderBytes is a maximum header size (including amino overhead). 34 MaxHeaderBytes int64 = 632 35 36 // MaxAminoOverheadForBlock - maximum amino overhead to encode a block (up to 37 // MaxBlockSizeBytes in size) not including it's parts except Data. 38 // This means it also excludes the overhead for individual transactions. 39 // To compute individual transactions' overhead use types.ComputeAminoOverhead(tx types.Tx, fieldNum int). 40 // 41 // Uvarint length of MaxBlockSizeBytes: 4 bytes 42 // 2 fields (2 embedded): 2 bytes 43 // Uvarint length of Data.Txs: 4 bytes 44 // Data.Txs field: 1 byte 45 MaxAminoOverheadForBlock int64 = 11 46 47 // CompressDividing is used to divide compressType and compressFlag of compressSign 48 // the compressSign = CompressType * CompressDividing + CompressFlag 49 CompressDividing int = 10 50 51 FlagBlockCompressType = "block-compress-type" 52 FlagBlockCompressFlag = "block-compress-flag" 53 FlagBlockCompressThreshold = "block-compress-threshold" 54 ) 55 56 var ( 57 BlockCompressType = 0x00 58 BlockCompressFlag = 0 59 BlockCompressThreshold = 1024000 60 ) 61 62 type BlockExInfo struct { 63 BlockCompressType int 64 BlockCompressFlag int 65 BlockPartSize int 66 } 67 68 func (info BlockExInfo) IsCompressed() bool { 69 return info.BlockCompressType != 0 70 } 71 72 // Block defines the atomic unit of a Tendermint blockchain. 73 type Block struct { 74 mtx sync.Mutex 75 76 Header `json:"header"` 77 Data `json:"data"` 78 Evidence EvidenceData `json:"evidence"` 79 LastCommit *Commit `json:"last_commit"` 80 } 81 82 func (b *Block) AminoSize(cdc *amino.Codec) int { 83 var size = 0 84 85 headerSize := b.Header.AminoSize(cdc) 86 if headerSize > 0 { 87 size += 1 + amino.UvarintSize(uint64(headerSize)) + headerSize 88 } 89 90 dataSize := b.Data.AminoSize(cdc) 91 if dataSize > 0 { 92 size += 1 + amino.UvarintSize(uint64(dataSize)) + dataSize 93 } 94 95 evidenceSize := b.Evidence.AminoSize(cdc) 96 if evidenceSize > 0 { 97 size += 1 + amino.UvarintSize(uint64(evidenceSize)) + evidenceSize 98 } 99 100 if b.LastCommit != nil { 101 commitSize := b.LastCommit.AminoSize(cdc) 102 size += 1 + amino.UvarintSize(uint64(commitSize)) + commitSize 103 } 104 105 return size 106 } 107 108 func (b *Block) UnmarshalFromAmino(cdc *amino.Codec, data []byte) error { 109 var dataLen uint64 = 0 110 var subData []byte 111 112 for { 113 data = data[dataLen:] 114 115 if len(data) == 0 { 116 break 117 } 118 119 pos, aminoType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0]) 120 if err != nil { 121 return err 122 } 123 data = data[1:] 124 125 if aminoType == amino.Typ3_ByteLength { 126 var n int 127 dataLen, n, err = amino.DecodeUvarint(data) 128 if err != nil { 129 return err 130 } 131 132 data = data[n:] 133 if len(data) < int(dataLen) { 134 return fmt.Errorf("not enough data to read field %d", pos) 135 } 136 subData = data[:dataLen] 137 } 138 139 switch pos { 140 case 1: 141 err = b.Header.UnmarshalFromAmino(cdc, subData) 142 if err != nil { 143 return err 144 } 145 case 2: 146 err = b.Data.UnmarshalFromAmino(cdc, subData) 147 if err != nil { 148 return err 149 } 150 case 3: 151 err = b.Evidence.UnmarshalFromAmino(cdc, subData) 152 if err != nil { 153 return err 154 } 155 case 4: 156 b.LastCommit = new(Commit) 157 err = b.LastCommit.UnmarshalFromAmino(cdc, subData) 158 if err != nil { 159 return err 160 } 161 default: 162 return fmt.Errorf("unexpect feild num %d", pos) 163 } 164 } 165 return nil 166 } 167 168 // ValidateBasic performs basic validation that doesn't involve state data. 169 // It checks the internal consistency of the block. 170 // Further validation is done using state#ValidateBlock. 171 func (b *Block) ValidateBasic() error { 172 if b == nil { 173 return errors.New("nil block") 174 } 175 176 b.mtx.Lock() 177 defer b.mtx.Unlock() 178 179 if err := b.Header.ValidateBasic(); err != nil { 180 return fmt.Errorf("invalid header: %w", err) 181 } 182 183 // Validate the last commit and its hash. 184 if b.Header.Height > GetStartBlockHeight()+1 { 185 if b.LastCommit == nil { 186 return errors.New("nil LastCommit") 187 } 188 if err := b.LastCommit.ValidateBasic(); err != nil { 189 return fmt.Errorf("wrong LastCommit: %v", err) 190 } 191 } 192 193 if !bytes.Equal(b.LastCommitHash, b.LastCommit.Hash()) { 194 return fmt.Errorf("wrong Header.LastCommitHash. Expected %v, got %v", 195 b.LastCommit.Hash(), 196 b.LastCommitHash, 197 ) 198 } 199 200 // NOTE: b.Data.Txs may be nil, but b.Data.Hash() still works fine. 201 if !bytes.Equal(b.DataHash, b.Data.Hash(b.Height)) { 202 return fmt.Errorf( 203 "wrong Header.DataHash. Expected %v, got %v", 204 b.Data.Hash(b.Height), 205 b.DataHash, 206 ) 207 } 208 209 // NOTE: b.Evidence.Evidence may be nil, but we're just looping. 210 for i, ev := range b.Evidence.Evidence { 211 if err := ev.ValidateBasic(); err != nil { 212 return fmt.Errorf("invalid evidence (#%d): %v", i, err) 213 } 214 } 215 216 if !bytes.Equal(b.EvidenceHash, b.Evidence.Hash()) { 217 return fmt.Errorf("wrong Header.EvidenceHash. Expected %v, got %v", 218 b.EvidenceHash, 219 b.Evidence.Hash(), 220 ) 221 } 222 223 return nil 224 } 225 226 // fillHeader fills in any remaining header fields that are a function of the block data 227 func (b *Block) fillHeader() { 228 if b.LastCommitHash == nil { 229 b.LastCommitHash = b.LastCommit.Hash() 230 } 231 if b.DataHash == nil { 232 b.DataHash = b.Data.Hash(b.Height) 233 } 234 if b.EvidenceHash == nil { 235 b.EvidenceHash = b.Evidence.Hash() 236 } 237 } 238 239 // Hash computes and returns the block hash. 240 // If the block is incomplete, block hash is nil for safety. 241 func (b *Block) Hash() tmbytes.HexBytes { 242 if b == nil { 243 return nil 244 } 245 b.mtx.Lock() 246 defer b.mtx.Unlock() 247 248 if b.LastCommit == nil { 249 return nil 250 } 251 b.fillHeader() 252 253 return b.Header.Hash() 254 } 255 256 // MakePartSet returns a PartSet containing parts of a serialized block. 257 // This is the form in which the block is gossipped to peers. 258 // CONTRACT: partSize is greater than zero. 259 func (b *Block) MakePartSet(partSize int) *PartSet { 260 return b.MakePartSetByExInfo(&BlockExInfo{ 261 BlockCompressType: BlockCompressType, 262 BlockCompressFlag: BlockCompressFlag, 263 BlockPartSize: partSize, 264 }) 265 } 266 267 func (b *Block) MakePartSetByExInfo(exInfo *BlockExInfo) *PartSet { 268 if b == nil { 269 return nil 270 } 271 if exInfo == nil { 272 exInfo = &BlockExInfo{ 273 BlockCompressType: BlockCompressType, 274 BlockCompressFlag: BlockCompressFlag, 275 BlockPartSize: BlockPartSizeBytes, 276 } 277 } 278 b.mtx.Lock() 279 defer b.mtx.Unlock() 280 281 // We prefix the byte length, so that unmarshaling 282 // can easily happen via a reader. 283 bz, err := cdc.MarshalBinaryLengthPrefixed(b) 284 if err != nil { 285 panic(err) 286 } 287 288 payload := compressBlock(bz, exInfo.BlockCompressType, exInfo.BlockCompressFlag) 289 290 return NewPartSetFromData(payload, exInfo.BlockPartSize) 291 292 } 293 294 func compressBlock(bz []byte, compressType, compressFlag int) []byte { 295 if compressType == 0 || len(bz) <= BlockCompressThreshold { 296 return bz 297 } 298 if compressType >= CompressDividing || compressFlag >= CompressDividing { 299 // unsupported compressType or compressFlag 300 return bz 301 } 302 303 t0 := tmtime.Now() 304 cz, err := compress.Compress(compressType, compressFlag, bz) 305 if err != nil { 306 return bz 307 } 308 t1 := tmtime.Now() 309 310 trace.GetElapsedInfo().AddInfo(trace.CompressBlock, fmt.Sprintf("%dms", t1.Sub(t0).Milliseconds())) 311 // tell receiver which compress type and flag 312 // tens digit is compressType and unit digit is compressFlag 313 // compressSign: XY means, compressType: X, compressFlag: Y 314 compressSign := compressType*CompressDividing + compressFlag 315 return append(cz, byte(compressSign)) 316 } 317 318 func UncompressBlockFromReader(pbpReader io.Reader) (io.Reader, error) { 319 // received compressed block bytes, uncompress with the flag:Proposal.CompressBlock 320 compressed, err := io.ReadAll(pbpReader) 321 if err != nil { 322 return nil, err 323 } 324 t0 := tmtime.Now() 325 original, compressSign, err := UncompressBlockFromBytes(compressed) 326 if err != nil { 327 return nil, err 328 } 329 t1 := tmtime.Now() 330 331 if compressSign != 0 { 332 compressRatio := float64(len(compressed)) / float64(len(original)) 333 trace.GetElapsedInfo().AddInfo(trace.UncompressBlock, fmt.Sprintf("%.2f/%dms", 334 compressRatio, t1.Sub(t0).Milliseconds())) 335 } 336 337 return bytes.NewBuffer(original), nil 338 } 339 340 // UncompressBlockFromBytes uncompress from compressBytes to blockPart bytes, and returns the compressSign 341 // compressSign contains compressType and compressFlag 342 // the compressSign: XY means, compressType: X, compressFlag: Y 343 func UncompressBlockFromBytes(payload []byte) (res []byte, compressSign int, err error) { 344 var buf bytes.Buffer 345 compressSign, err = UncompressBlockFromBytesTo(payload, &buf) 346 if err == nil && compressSign == 0 { 347 return payload, 0, nil 348 } 349 res = buf.Bytes() 350 return 351 } 352 353 func IsBlockDataCompressed(payload []byte) bool { 354 // try parse Uvarint to check if it is compressed 355 compressBytesLen, n := binary.Uvarint(payload) 356 if compressBytesLen == uint64(len(payload)-n) { 357 return false 358 } else { 359 return true 360 } 361 } 362 363 // UncompressBlockFromBytesTo uncompress payload to buf, and returns the compressSign, 364 // if payload is not compressed, compressSign will be 0, and buf will not be changed. 365 func UncompressBlockFromBytesTo(payload []byte, buf *bytes.Buffer) (compressSign int, err error) { 366 if IsBlockDataCompressed(payload) { 367 // the block has compressed and the last byte is compressSign 368 compressSign = int(payload[len(payload)-1]) 369 err = compress.UnCompressTo(compressSign/CompressDividing, payload[:len(payload)-1], buf) 370 } 371 return 372 } 373 374 // HashesTo is a convenience function that checks if a block hashes to the given argument. 375 // Returns false if the block is nil or the hash is empty. 376 func (b *Block) HashesTo(hash []byte) bool { 377 if len(hash) == 0 { 378 return false 379 } 380 if b == nil { 381 return false 382 } 383 return bytes.Equal(b.Hash(), hash) 384 } 385 386 // Size returns size of the block in bytes. 387 func (b *Block) Size() int { 388 bz, err := cdc.MarshalBinaryBare(b) 389 if err != nil { 390 return 0 391 } 392 return len(bz) 393 } 394 395 // TODO : Replace the original logic of Size with the logic of FastSize 396 397 // FastSize returns size of the block in bytes. and more efficient than Size(). 398 // But we can't make sure it's completely correct yet, when we're done testing, we'll replace Size with FastSize 399 func (b *Block) FastSize() (size int) { 400 defer func() { 401 if r := recover(); r != nil { 402 size = 0 403 } 404 }() 405 return b.AminoSize(cdc) 406 } 407 408 // String returns a string representation of the block 409 func (b *Block) String() string { 410 return b.StringIndented("") 411 } 412 413 // StringIndented returns a string representation of the block 414 func (b *Block) StringIndented(indent string) string { 415 if b == nil { 416 return "nil-Block" 417 } 418 return fmt.Sprintf(`Block{ 419 %s %v 420 %s %v 421 %s %v 422 %s %v 423 %s}#%v`, 424 indent, b.Header.StringIndented(indent+" "), 425 indent, b.Data.StringIndented(indent+" ", b.Height), 426 indent, b.Evidence.StringIndented(indent+" "), 427 indent, b.LastCommit.StringIndented(indent+" "), 428 indent, b.Hash()) 429 } 430 431 // StringShort returns a shortened string representation of the block 432 func (b *Block) StringShort() string { 433 if b == nil { 434 return "nil-Block" 435 } 436 return fmt.Sprintf("Block#%v", b.Hash()) 437 } 438 439 //----------------------------------------------------------- 440 // These methods are for Protobuf Compatibility 441 442 // Marshal returns the amino encoding. 443 func (b *Block) Marshal() ([]byte, error) { 444 return cdc.MarshalBinaryBare(b) 445 } 446 447 // MarshalTo calls Marshal and copies to the given buffer. 448 func (b *Block) MarshalTo(data []byte) (int, error) { 449 bs, err := b.Marshal() 450 if err != nil { 451 return -1, err 452 } 453 return copy(data, bs), nil 454 } 455 456 // Unmarshal deserializes from amino encoded form. 457 func (b *Block) Unmarshal(bs []byte) error { 458 return cdc.UnmarshalBinaryBare(bs, b) 459 } 460 461 //----------------------------------------------------------------------------- 462 463 // MaxDataBytes returns the maximum size of block's data. 464 // 465 // XXX: Panics on negative result. 466 func MaxDataBytes(maxBytes int64, valsCount, evidenceCount int) int64 { 467 maxDataBytes := maxBytes - 468 MaxAminoOverheadForBlock - 469 MaxHeaderBytes - 470 int64(valsCount)*MaxVoteBytes - 471 int64(evidenceCount)*MaxEvidenceBytes 472 473 if maxDataBytes < 0 { 474 panic(fmt.Sprintf( 475 "Negative MaxDataBytes. Block.MaxBytes=%d is too small to accommodate header&lastCommit&evidence=%d", 476 maxBytes, 477 -(maxDataBytes - maxBytes), 478 )) 479 } 480 481 return maxDataBytes 482 483 } 484 485 // MaxDataBytesUnknownEvidence returns the maximum size of block's data when 486 // evidence count is unknown. MaxEvidencePerBlock will be used for the size 487 // of evidence. 488 // 489 // XXX: Panics on negative result. 490 func MaxDataBytesUnknownEvidence(maxBytes int64, valsCount int) int64 { 491 _, maxEvidenceBytes := MaxEvidencePerBlock(maxBytes) 492 maxDataBytes := maxBytes - 493 MaxAminoOverheadForBlock - 494 MaxHeaderBytes - 495 int64(valsCount)*MaxVoteBytes - 496 maxEvidenceBytes 497 498 if maxDataBytes < 0 { 499 panic(fmt.Sprintf( 500 "Negative MaxDataBytesUnknownEvidence. Block.MaxBytes=%d is too small to accommodate header&lastCommit&evidence=%d", 501 maxBytes, 502 -(maxDataBytes - maxBytes), 503 )) 504 } 505 506 return maxDataBytes 507 } 508 509 //----------------------------------------------------------------------------- 510 511 // Header defines the structure of a Tendermint block header. 512 // NOTE: changes to the Header should be duplicated in: 513 // - header.Hash() 514 // - abci.Header 515 // - https://github.com/tendermint/spec/blob/master/spec/blockchain/blockchain.md 516 type Header struct { 517 // basic block info 518 Version version.Consensus `json:"version"` 519 ChainID string `json:"chain_id"` 520 Height int64 `json:"height"` 521 Time time.Time `json:"time"` 522 523 // prev block info 524 LastBlockID BlockID `json:"last_block_id"` 525 526 // hashes of block data 527 LastCommitHash tmbytes.HexBytes `json:"last_commit_hash"` // commit from validators from the last block 528 DataHash tmbytes.HexBytes `json:"data_hash"` // transactions 529 530 // hashes from the app output from the prev block 531 ValidatorsHash tmbytes.HexBytes `json:"validators_hash"` // validators for the current block 532 NextValidatorsHash tmbytes.HexBytes `json:"next_validators_hash"` // validators for the next block 533 ConsensusHash tmbytes.HexBytes `json:"consensus_hash"` // consensus params for current block 534 AppHash tmbytes.HexBytes `json:"app_hash"` // state after txs from the previous block 535 // root hash of all results from the txs from the previous block 536 LastResultsHash tmbytes.HexBytes `json:"last_results_hash"` 537 538 // consensus info 539 EvidenceHash tmbytes.HexBytes `json:"evidence_hash"` // evidence included in the block 540 ProposerAddress Address `json:"proposer_address"` // original proposer of the block 541 } 542 543 func (h Header) AminoSize(cdc *amino.Codec) int { 544 var size int 545 546 versionSize := h.Version.AminoSize() 547 if versionSize > 0 { 548 size += 1 + amino.UvarintSize(uint64(versionSize)) + versionSize 549 } 550 551 if h.ChainID != "" { 552 size += 1 + amino.UvarintSize(uint64(len(h.ChainID))) + len(h.ChainID) 553 } 554 555 if h.Height != 0 { 556 size += 1 + amino.UvarintSize(uint64(h.Height)) 557 } 558 559 timeSize := amino.TimeSize(h.Time) 560 if timeSize > 0 { 561 size += 1 + amino.UvarintSize(uint64(timeSize)) + timeSize 562 } 563 564 blockIDSize := h.LastBlockID.AminoSize(cdc) 565 if blockIDSize > 0 { 566 size += 1 + amino.UvarintSize(uint64(blockIDSize)) + blockIDSize 567 } 568 569 if len(h.LastCommitHash) != 0 { 570 size += 1 + amino.ByteSliceSize(h.LastCommitHash) 571 } 572 573 if len(h.DataHash) != 0 { 574 size += 1 + amino.ByteSliceSize(h.DataHash) 575 } 576 577 if len(h.ValidatorsHash) != 0 { 578 size += 1 + amino.ByteSliceSize(h.ValidatorsHash) 579 } 580 581 if len(h.NextValidatorsHash) != 0 { 582 size += 1 + amino.ByteSliceSize(h.NextValidatorsHash) 583 } 584 585 if len(h.ConsensusHash) != 0 { 586 size += 1 + amino.ByteSliceSize(h.ConsensusHash) 587 } 588 589 if len(h.AppHash) != 0 { 590 size += 1 + amino.ByteSliceSize(h.AppHash) 591 } 592 593 if len(h.LastResultsHash) != 0 { 594 size += 1 + amino.ByteSliceSize(h.LastResultsHash) 595 } 596 597 if len(h.EvidenceHash) != 0 { 598 size += 1 + amino.ByteSliceSize(h.EvidenceHash) 599 } 600 601 if len(h.ProposerAddress) != 0 { 602 size += 1 + amino.ByteSliceSize(h.ProposerAddress) 603 } 604 605 return size 606 } 607 608 func (h *Header) UnmarshalFromAmino(cdc *amino.Codec, data []byte) error { 609 var dataLen uint64 = 0 610 var subData []byte 611 var timeUpdated = false 612 613 for { 614 data = data[dataLen:] 615 616 if len(data) == 0 { 617 break 618 } 619 620 pos, aminoType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0]) 621 if err != nil { 622 return err 623 } 624 data = data[1:] 625 626 if aminoType == amino.Typ3_ByteLength { 627 var n int 628 dataLen, n, err = amino.DecodeUvarint(data) 629 if err != nil { 630 return err 631 } 632 633 data = data[n:] 634 if len(data) < int(dataLen) { 635 return fmt.Errorf("not enough data for field, need %d, have %d", dataLen, len(data)) 636 } 637 subData = data[:dataLen] 638 } 639 640 switch pos { 641 case 1: 642 err = h.Version.UnmarshalFromAmino(cdc, subData) 643 if err != nil { 644 return err 645 } 646 case 2: 647 h.ChainID = string(subData) 648 case 3: 649 uvint, n, err := amino.DecodeUvarint(data) 650 if err != nil { 651 return err 652 } 653 h.Height = int64(uvint) 654 dataLen = uint64(n) 655 case 4: 656 h.Time, _, err = amino.DecodeTime(subData) 657 if err != nil { 658 return err 659 } 660 timeUpdated = true 661 case 5: 662 err = h.LastBlockID.UnmarshalFromAmino(cdc, subData) 663 if err != nil { 664 return err 665 } 666 case 6: 667 h.LastCommitHash = make([]byte, len(subData)) 668 copy(h.LastCommitHash, subData) 669 case 7: 670 h.DataHash = make([]byte, len(subData)) 671 copy(h.DataHash, subData) 672 case 8: 673 h.ValidatorsHash = make([]byte, len(subData)) 674 copy(h.ValidatorsHash, subData) 675 case 9: 676 h.NextValidatorsHash = make([]byte, len(subData)) 677 copy(h.NextValidatorsHash, subData) 678 case 10: 679 h.ConsensusHash = make([]byte, len(subData)) 680 copy(h.ConsensusHash, subData) 681 case 11: 682 h.AppHash = make([]byte, len(subData)) 683 copy(h.AppHash, subData) 684 case 12: 685 h.LastResultsHash = make([]byte, len(subData)) 686 copy(h.LastResultsHash, subData) 687 case 13: 688 h.EvidenceHash = make([]byte, len(subData)) 689 copy(h.EvidenceHash, subData) 690 case 14: 691 h.ProposerAddress = make([]byte, len(subData)) 692 copy(h.ProposerAddress, subData) 693 default: 694 return fmt.Errorf("unexpect feild num %d", pos) 695 } 696 } 697 if !timeUpdated { 698 h.Time = amino.ZeroTime 699 } 700 return nil 701 } 702 703 // Populate the Header with state-derived data. 704 // Call this after MakeBlock to complete the Header. 705 func (h *Header) Populate( 706 version version.Consensus, chainID string, 707 timestamp time.Time, lastBlockID BlockID, 708 valHash, nextValHash []byte, 709 consensusHash, appHash, lastResultsHash []byte, 710 proposerAddress Address, 711 ) { 712 h.Version = version 713 h.ChainID = chainID 714 h.Time = timestamp 715 h.LastBlockID = lastBlockID 716 h.ValidatorsHash = valHash 717 h.NextValidatorsHash = nextValHash 718 h.ConsensusHash = consensusHash 719 h.AppHash = appHash 720 h.LastResultsHash = lastResultsHash 721 h.ProposerAddress = proposerAddress 722 } 723 724 // ValidateBasic performs stateless validation on a Header returning an error 725 // if any validation fails. 726 // 727 // NOTE: Timestamp validation is subtle and handled elsewhere. 728 func (h Header) ValidateBasic() error { 729 if len(h.ChainID) > MaxChainIDLen { 730 return fmt.Errorf("chainID is too long; got: %d, max: %d", len(h.ChainID), MaxChainIDLen) 731 } 732 733 if h.Height < 0 { 734 return errors.New("negative Height") 735 } else if h.Height == 0 { 736 return errors.New("zero Height") 737 } 738 739 if err := h.LastBlockID.ValidateBasic(); err != nil { 740 return fmt.Errorf("wrong LastBlockID: %w", err) 741 } 742 743 if err := ValidateHash(h.LastCommitHash); err != nil { 744 return fmt.Errorf("wrong LastCommitHash: %v", err) 745 } 746 747 if err := ValidateHash(h.DataHash); err != nil { 748 return fmt.Errorf("wrong DataHash: %v", err) 749 } 750 751 if err := ValidateHash(h.EvidenceHash); err != nil { 752 return fmt.Errorf("wrong EvidenceHash: %v", err) 753 } 754 755 if len(h.ProposerAddress) != crypto.AddressSize { 756 return fmt.Errorf( 757 "invalid ProposerAddress length; got: %d, expected: %d", 758 len(h.ProposerAddress), crypto.AddressSize, 759 ) 760 } 761 762 // Basic validation of hashes related to application data. 763 // Will validate fully against state in state#ValidateBlock. 764 if err := ValidateHash(h.ValidatorsHash); err != nil { 765 return fmt.Errorf("wrong ValidatorsHash: %v", err) 766 } 767 if err := ValidateHash(h.NextValidatorsHash); err != nil { 768 return fmt.Errorf("wrong NextValidatorsHash: %v", err) 769 } 770 if err := ValidateHash(h.ConsensusHash); err != nil { 771 return fmt.Errorf("wrong ConsensusHash: %v", err) 772 } 773 // NOTE: AppHash is arbitrary length 774 if err := ValidateHash(h.LastResultsHash); err != nil { 775 return fmt.Errorf("wrong LastResultsHash: %v", err) 776 } 777 778 return nil 779 } 780 781 // Hash returns the hash of the header. 782 // It computes a Merkle tree from the header fields 783 // ordered as they appear in the Header. 784 // Returns nil if ValidatorHash is missing, 785 // since a Header is not valid unless there is 786 // a ValidatorsHash (corresponding to the validator set). 787 788 func (h *Header) Hash() tmbytes.HexBytes { 789 if h == nil || len(h.ValidatorsHash) == 0 { 790 return nil 791 } 792 if HigherThanVenus1(h.Height) { 793 return h.IBCHash() 794 } 795 return h.originHash() 796 } 797 func (h *Header) originHash() tmbytes.HexBytes { 798 return merkle.SimpleHashFromByteSlices([][]byte{ 799 cdcEncode(h.Version), 800 cdcEncode(h.ChainID), 801 cdcEncode(h.Height), 802 cdcEncode(h.Time), 803 cdcEncode(h.LastBlockID), 804 cdcEncode(h.LastCommitHash), 805 cdcEncode(h.DataHash), 806 cdcEncode(h.ValidatorsHash), 807 cdcEncode(h.NextValidatorsHash), 808 cdcEncode(h.ConsensusHash), 809 cdcEncode(h.AppHash), 810 cdcEncode(h.LastResultsHash), 811 cdcEncode(h.EvidenceHash), 812 cdcEncode(h.ProposerAddress), 813 }) 814 } 815 816 func (h *Header) IBCHash() tmbytes.HexBytes { 817 if h == nil || len(h.ValidatorsHash) == 0 { 818 return nil 819 } 820 hbz, err := h.Version.Marshal() 821 if err != nil { 822 return nil 823 } 824 pbt, err := gogotypes.StdTimeMarshal(h.Time) 825 if err != nil { 826 return nil 827 } 828 829 pbbi := h.LastBlockID.ToIBCProto() 830 bzbi, err := pbbi.Marshal() 831 if err != nil { 832 return nil 833 } 834 ret := merkle.HashFromByteSlices([][]byte{ 835 hbz, 836 ibccdcEncode(h.ChainID), 837 ibccdcEncode(h.Height), 838 pbt, 839 bzbi, 840 ibccdcEncode(h.LastCommitHash), 841 ibccdcEncode(h.DataHash), 842 ibccdcEncode(h.ValidatorsHash), 843 ibccdcEncode(h.NextValidatorsHash), 844 ibccdcEncode(h.ConsensusHash), 845 ibccdcEncode(h.AppHash), 846 ibccdcEncode(h.LastResultsHash), 847 ibccdcEncode(h.EvidenceHash), 848 ibccdcEncode(h.ProposerAddress), 849 }) 850 return ret 851 } 852 853 // StringIndented returns a string representation of the header 854 func (h *Header) StringIndented(indent string) string { 855 if h == nil { 856 return "nil-Header" 857 } 858 return fmt.Sprintf(`Header{ 859 %s Version: %v 860 %s ChainID: %v 861 %s Height: %v 862 %s Time: %v 863 %s LastBlockID: %v 864 %s LastCommit: %v 865 %s Data: %v 866 %s Validators: %v 867 %s NextValidators: %v 868 %s App: %v 869 %s Consensus: %v 870 %s Results: %v 871 %s Evidence: %v 872 %s Proposer: %v 873 %s}#%v`, 874 indent, h.Version, 875 indent, h.ChainID, 876 indent, h.Height, 877 indent, h.Time, 878 indent, h.LastBlockID, 879 indent, h.LastCommitHash, 880 indent, h.DataHash, 881 indent, h.ValidatorsHash, 882 indent, h.NextValidatorsHash, 883 indent, h.AppHash, 884 indent, h.ConsensusHash, 885 indent, h.LastResultsHash, 886 indent, h.EvidenceHash, 887 indent, h.ProposerAddress, 888 indent, h.Hash()) 889 } 890 891 // ToProto converts Header to protobuf 892 func (h *Header) ToProto() *tmproto.Header { 893 if h == nil { 894 return nil 895 } 896 return &tmproto.Header{ 897 Version: tmversion.Consensus{Block: h.Version.Block.Uint64(), App: h.Version.App.Uint64()}, 898 ChainID: h.ChainID, 899 Height: h.Height, 900 Time: h.Time, 901 LastBlockID: h.LastBlockID.ToProto(), 902 ValidatorsHash: h.ValidatorsHash, 903 NextValidatorsHash: h.NextValidatorsHash, 904 ConsensusHash: h.ConsensusHash, 905 AppHash: h.AppHash, 906 DataHash: h.DataHash, 907 EvidenceHash: h.EvidenceHash, 908 LastResultsHash: h.LastResultsHash, 909 LastCommitHash: h.LastCommitHash, 910 ProposerAddress: h.ProposerAddress, 911 } 912 } 913 914 // FromProto sets a protobuf Header to the given pointer. 915 // It returns an error if the header is invalid. 916 func HeaderFromProto(ph *tmproto.Header) (Header, error) { 917 if ph == nil { 918 return Header{}, errors.New("nil Header") 919 } 920 921 h := new(Header) 922 923 bi, err := BlockIDFromProto(&ph.LastBlockID) 924 if err != nil { 925 return Header{}, err 926 } 927 928 h.Version = version.Consensus{Block: version.Protocol(ph.Version.Block), App: version.Protocol(ph.Version.App)} 929 h.ChainID = ph.ChainID 930 h.Height = ph.Height 931 h.Time = ph.Time 932 h.Height = ph.Height 933 h.LastBlockID = *bi 934 h.ValidatorsHash = ph.ValidatorsHash 935 h.NextValidatorsHash = ph.NextValidatorsHash 936 h.ConsensusHash = ph.ConsensusHash 937 h.AppHash = ph.AppHash 938 h.DataHash = ph.DataHash 939 h.EvidenceHash = ph.EvidenceHash 940 h.LastResultsHash = ph.LastResultsHash 941 h.LastCommitHash = ph.LastCommitHash 942 h.ProposerAddress = ph.ProposerAddress 943 944 return *h, h.ValidateBasic() 945 } 946 947 //------------------------------------- 948 949 // BlockIDFlag indicates which BlockID the signature is for. 950 type BlockIDFlag byte 951 952 const ( 953 // BlockIDFlagAbsent - no vote was received from a validator. 954 BlockIDFlagAbsent BlockIDFlag = iota + 1 955 // BlockIDFlagCommit - voted for the Commit.BlockID. 956 BlockIDFlagCommit 957 // BlockIDFlagNil - voted for nil. 958 BlockIDFlagNil 959 ) 960 961 // CommitSig is a part of the Vote included in a Commit. 962 type CommitSig struct { 963 BlockIDFlag BlockIDFlag `json:"block_id_flag"` 964 ValidatorAddress Address `json:"validator_address"` 965 Timestamp time.Time `json:"timestamp"` 966 Signature []byte `json:"signature"` 967 } 968 969 func (cs CommitSig) AminoSize(_ *amino.Codec) int { 970 var size = 0 971 972 if cs.BlockIDFlag != 0 { 973 size += 1 + amino.UvarintSize(uint64(cs.BlockIDFlag)) 974 } 975 976 if len(cs.ValidatorAddress) != 0 { 977 size += 1 + amino.ByteSliceSize(cs.ValidatorAddress) 978 } 979 980 timestampSize := amino.TimeSize(cs.Timestamp) 981 if timestampSize > 0 { 982 size += 1 + amino.UvarintSize(uint64(timestampSize)) + timestampSize 983 } 984 985 if len(cs.Signature) != 0 { 986 size += 1 + amino.ByteSliceSize(cs.Signature) 987 } 988 989 return size 990 } 991 992 func (cs *CommitSig) UnmarshalFromAmino(_ *amino.Codec, data []byte) error { 993 var dataLen uint64 = 0 994 var subData []byte 995 var timestampUpdated bool 996 997 for { 998 data = data[dataLen:] 999 if len(data) == 0 { 1000 break 1001 } 1002 1003 pos, pbType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0]) 1004 if err != nil { 1005 return err 1006 } 1007 data = data[1:] 1008 1009 if pbType == amino.Typ3_ByteLength { 1010 var n int 1011 dataLen, n, err = amino.DecodeUvarint(data) 1012 if err != nil { 1013 return err 1014 } 1015 data = data[n:] 1016 if len(data) < int(dataLen) { 1017 return fmt.Errorf("invalid data len") 1018 } 1019 subData = data[:dataLen] 1020 } 1021 1022 switch pos { 1023 case 1: 1024 u64, n, err := amino.DecodeUvarint(data) 1025 if err != nil { 1026 return err 1027 } 1028 cs.BlockIDFlag = BlockIDFlag(u64) 1029 dataLen = uint64(n) 1030 case 2: 1031 cs.ValidatorAddress = make([]byte, len(subData)) 1032 copy(cs.ValidatorAddress, subData) 1033 case 3: 1034 cs.Timestamp, _, err = amino.DecodeTime(subData) 1035 if err != nil { 1036 return err 1037 } 1038 timestampUpdated = true 1039 case 4: 1040 cs.Signature = make([]byte, len(subData)) 1041 copy(cs.Signature, subData) 1042 default: 1043 return fmt.Errorf("unexpect feild num %d", pos) 1044 } 1045 } 1046 if !timestampUpdated { 1047 cs.Timestamp = amino.ZeroTime 1048 } 1049 return nil 1050 } 1051 1052 // NewCommitSigForBlock returns new CommitSig with BlockIDFlagCommit. 1053 func NewCommitSigForBlock(signature []byte, valAddr Address, ts time.Time) CommitSig { 1054 return CommitSig{ 1055 BlockIDFlag: BlockIDFlagCommit, 1056 ValidatorAddress: valAddr, 1057 Timestamp: ts, 1058 Signature: signature, 1059 } 1060 } 1061 1062 // ForBlock returns true if CommitSig is for the block. 1063 func (cs CommitSig) ForBlock() bool { 1064 return cs.BlockIDFlag == BlockIDFlagCommit 1065 } 1066 1067 // NewCommitSigAbsent returns new CommitSig with BlockIDFlagAbsent. Other 1068 // fields are all empty. 1069 func NewCommitSigAbsent() CommitSig { 1070 return CommitSig{ 1071 BlockIDFlag: BlockIDFlagAbsent, 1072 } 1073 } 1074 1075 // Absent returns true if CommitSig is absent. 1076 func (cs CommitSig) Absent() bool { 1077 return cs.BlockIDFlag == BlockIDFlagAbsent 1078 } 1079 1080 func (cs CommitSig) String() string { 1081 return fmt.Sprintf("CommitSig{%X by %X on %v @ %s}", 1082 tmbytes.Fingerprint(cs.Signature), 1083 tmbytes.Fingerprint(cs.ValidatorAddress), 1084 cs.BlockIDFlag, 1085 CanonicalTime(cs.Timestamp)) 1086 } 1087 1088 // BlockID returns the Commit's BlockID if CommitSig indicates signing, 1089 // otherwise - empty BlockID. 1090 func (cs CommitSig) BlockID(commitBlockID BlockID) BlockID { 1091 var blockID BlockID 1092 switch cs.BlockIDFlag { 1093 case BlockIDFlagAbsent: 1094 blockID = BlockID{} 1095 case BlockIDFlagCommit: 1096 blockID = commitBlockID 1097 case BlockIDFlagNil: 1098 blockID = BlockID{} 1099 default: 1100 panic(fmt.Sprintf("Unknown BlockIDFlag: %v", cs.BlockIDFlag)) 1101 } 1102 return blockID 1103 } 1104 1105 // ValidateBasic performs basic validation. 1106 func (cs CommitSig) ValidateBasic() error { 1107 switch cs.BlockIDFlag { 1108 case BlockIDFlagAbsent: 1109 case BlockIDFlagCommit: 1110 case BlockIDFlagNil: 1111 default: 1112 return fmt.Errorf("unknown BlockIDFlag: %v", cs.BlockIDFlag) 1113 } 1114 1115 switch cs.BlockIDFlag { 1116 case BlockIDFlagAbsent: 1117 if len(cs.ValidatorAddress) != 0 { 1118 return errors.New("validator address is present") 1119 } 1120 if !cs.Timestamp.IsZero() { 1121 return errors.New("time is present") 1122 } 1123 if len(cs.Signature) != 0 { 1124 return errors.New("signature is present") 1125 } 1126 default: 1127 if len(cs.ValidatorAddress) != crypto.AddressSize { 1128 return fmt.Errorf("expected ValidatorAddress size to be %d bytes, got %d bytes", 1129 crypto.AddressSize, 1130 len(cs.ValidatorAddress), 1131 ) 1132 } 1133 // NOTE: Timestamp validation is subtle and handled elsewhere. 1134 if len(cs.Signature) == 0 { 1135 return errors.New("signature is missing") 1136 } 1137 if len(cs.Signature) > MaxSignatureSize { 1138 return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize) 1139 } 1140 } 1141 1142 return nil 1143 } 1144 1145 // ToProto converts CommitSig to protobuf 1146 func (cs *CommitSig) ToProto() *tmproto.CommitSig { 1147 if cs == nil { 1148 return nil 1149 } 1150 1151 return &tmproto.CommitSig{ 1152 BlockIdFlag: tmproto.BlockIDFlag(cs.BlockIDFlag), 1153 ValidatorAddress: cs.ValidatorAddress, 1154 Timestamp: cs.Timestamp, 1155 Signature: cs.Signature, 1156 } 1157 } 1158 1159 // FromProto sets a protobuf CommitSig to the given pointer. 1160 // It returns an error if the CommitSig is invalid. 1161 func (cs *CommitSig) FromProto(csp tmproto.CommitSig) error { 1162 1163 cs.BlockIDFlag = BlockIDFlag(csp.BlockIdFlag) 1164 cs.ValidatorAddress = csp.ValidatorAddress 1165 cs.Timestamp = csp.Timestamp 1166 cs.Signature = csp.Signature 1167 1168 return cs.ValidateBasic() 1169 } 1170 1171 //------------------------------------- 1172 1173 // Commit contains the evidence that a block was committed by a set of validators. 1174 // NOTE: Commit is empty for height 1, but never nil. 1175 type Commit struct { 1176 // NOTE: The signatures are in order of address to preserve the bonded 1177 // ValidatorSet order. 1178 // Any peer with a block can gossip signatures by index with a peer without 1179 // recalculating the active ValidatorSet. 1180 Height int64 `json:"height"` 1181 Round int `json:"round"` 1182 BlockID BlockID `json:"block_id"` 1183 Signatures []CommitSig `json:"signatures"` 1184 1185 // Memoized in first call to corresponding method. 1186 // NOTE: can't memoize in constructor because constructor isn't used for 1187 // unmarshaling. 1188 hash tmbytes.HexBytes 1189 bitArray *bits.BitArray 1190 } 1191 1192 func (commit Commit) AminoSize(cdc *amino.Codec) int { 1193 var size int = 0 1194 1195 if commit.Height != 0 { 1196 size += 1 + amino.UvarintSize(uint64(commit.Height)) 1197 } 1198 1199 if commit.Round != 0 { 1200 size += 1 + amino.UvarintSize(uint64(commit.Round)) 1201 } 1202 1203 blockIDSize := commit.BlockID.AminoSize(cdc) 1204 if blockIDSize > 0 { 1205 size += 1 + amino.UvarintSize(uint64(blockIDSize)) + blockIDSize 1206 } 1207 1208 for _, sig := range commit.Signatures { 1209 sigSize := sig.AminoSize(cdc) 1210 size += 1 + amino.UvarintSize(uint64(sigSize)) + sigSize 1211 } 1212 1213 return size 1214 } 1215 1216 func (commit *Commit) UnmarshalFromAmino(cdc *amino.Codec, data []byte) error { 1217 var dataLen uint64 = 0 1218 var subData []byte 1219 1220 for { 1221 data = data[dataLen:] 1222 if len(data) == 0 { 1223 break 1224 } 1225 1226 pos, pbType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0]) 1227 if err != nil { 1228 return err 1229 } 1230 data = data[1:] 1231 1232 if pbType == amino.Typ3_ByteLength { 1233 var n int 1234 dataLen, n, err = amino.DecodeUvarint(data) 1235 if err != nil { 1236 return err 1237 } 1238 data = data[n:] 1239 if len(data) < int(dataLen) { 1240 return fmt.Errorf("invalid data len") 1241 } 1242 subData = data[:dataLen] 1243 } 1244 1245 switch pos { 1246 case 1: 1247 u64, n, err := amino.DecodeUvarint(data) 1248 if err != nil { 1249 return err 1250 } 1251 commit.Height = int64(u64) 1252 dataLen = uint64(n) 1253 case 2: 1254 u64, n, err := amino.DecodeUvarint(data) 1255 if err != nil { 1256 return err 1257 } 1258 commit.Round = int(u64) 1259 dataLen = uint64(n) 1260 case 3: 1261 err = commit.BlockID.UnmarshalFromAmino(cdc, subData) 1262 if err != nil { 1263 return err 1264 } 1265 case 4: 1266 var cs CommitSig 1267 err = cs.UnmarshalFromAmino(cdc, subData) 1268 if err != nil { 1269 return err 1270 } 1271 commit.Signatures = append(commit.Signatures, cs) 1272 default: 1273 return fmt.Errorf("unexpect feild num %d", pos) 1274 } 1275 } 1276 return nil 1277 } 1278 1279 // NewCommit returns a new Commit. 1280 func NewCommit(height int64, round int, blockID BlockID, commitSigs []CommitSig) *Commit { 1281 return &Commit{ 1282 Height: height, 1283 Round: round, 1284 BlockID: blockID, 1285 Signatures: commitSigs, 1286 } 1287 } 1288 1289 // CommitToVoteSet constructs a VoteSet from the Commit and validator set. 1290 // Panics if signatures from the commit can't be added to the voteset. 1291 // Inverse of VoteSet.MakeCommit(). 1292 func CommitToVoteSet(chainID string, commit *Commit, vals *ValidatorSet) *VoteSet { 1293 voteSet := NewVoteSet(chainID, commit.Height, commit.Round, PrecommitType, vals) 1294 for idx, commitSig := range commit.Signatures { 1295 if commitSig.Absent() { 1296 continue // OK, some precommits can be missing. 1297 } 1298 added, err := voteSet.AddVote(commit.GetVote(idx)) 1299 if !added || err != nil { 1300 panic(fmt.Sprintf("Failed to reconstruct LastCommit: %v", err)) 1301 } 1302 } 1303 return voteSet 1304 } 1305 1306 // GetVote converts the CommitSig for the given valIdx to a Vote. 1307 // Returns nil if the precommit at valIdx is nil. 1308 // Panics if valIdx >= commit.Size(). 1309 func (commit *Commit) GetVote(valIdx int) *Vote { 1310 commitSig := commit.Signatures[valIdx] 1311 return &Vote{ 1312 Type: PrecommitType, 1313 Height: commit.Height, 1314 Round: commit.Round, 1315 BlockID: commitSig.BlockID(commit.BlockID), 1316 Timestamp: commitSig.Timestamp, 1317 ValidatorAddress: commitSig.ValidatorAddress, 1318 ValidatorIndex: valIdx, 1319 Signature: commitSig.Signature, 1320 } 1321 } 1322 1323 // VoteSignBytes constructs the SignBytes for the given CommitSig. 1324 // The only unique part of the SignBytes is the Timestamp - all other fields 1325 // signed over are otherwise the same for all validators. 1326 // Panics if valIdx >= commit.Size(). 1327 func (commit *Commit) VoteSignBytes(chainID string, valIdx int) []byte { 1328 return commit.GetVote(valIdx).SignBytes(chainID) 1329 } 1330 1331 // Type returns the vote type of the commit, which is always VoteTypePrecommit 1332 // Implements VoteSetReader. 1333 func (commit *Commit) Type() byte { 1334 return byte(PrecommitType) 1335 } 1336 1337 // GetHeight returns height of the commit. 1338 // Implements VoteSetReader. 1339 func (commit *Commit) GetHeight() int64 { 1340 return commit.Height 1341 } 1342 1343 // GetRound returns height of the commit. 1344 // Implements VoteSetReader. 1345 func (commit *Commit) GetRound() int { 1346 return commit.Round 1347 } 1348 1349 // Size returns the number of signatures in the commit. 1350 // Implements VoteSetReader. 1351 func (commit *Commit) Size() int { 1352 if commit == nil { 1353 return 0 1354 } 1355 return len(commit.Signatures) 1356 } 1357 1358 // BitArray returns a BitArray of which validators voted for BlockID or nil in this commit. 1359 // Implements VoteSetReader. 1360 func (commit *Commit) BitArray() *bits.BitArray { 1361 if commit.bitArray == nil { 1362 commit.bitArray = bits.NewBitArray(len(commit.Signatures)) 1363 for i, commitSig := range commit.Signatures { 1364 // TODO: need to check the BlockID otherwise we could be counting conflicts, 1365 // not just the one with +2/3 ! 1366 commit.bitArray.SetIndex(i, !commitSig.Absent()) 1367 } 1368 } 1369 return commit.bitArray 1370 } 1371 1372 // GetByIndex returns the vote corresponding to a given validator index. 1373 // Panics if `index >= commit.Size()`. 1374 // Implements VoteSetReader. 1375 func (commit *Commit) GetByIndex(valIdx int) *Vote { 1376 return commit.GetVote(valIdx) 1377 } 1378 1379 // IsCommit returns true if there is at least one signature. 1380 // Implements VoteSetReader. 1381 func (commit *Commit) IsCommit() bool { 1382 return len(commit.Signatures) != 0 1383 } 1384 1385 // ValidateBasic performs basic validation that doesn't involve state data. 1386 // Does not actually check the cryptographic signatures. 1387 func (commit *Commit) ValidateBasic() error { 1388 if commit.Height < 0 { 1389 return errors.New("negative Height") 1390 } 1391 if commit.Round < 0 { 1392 return errors.New("negative Round") 1393 } 1394 if commit.Height >= 1 { 1395 if commit.BlockID.IsZero() { 1396 return errors.New("commit cannot be for nil block") 1397 } 1398 1399 if len(commit.Signatures) == 0 { 1400 return errors.New("no signatures in commit") 1401 } 1402 for i, commitSig := range commit.Signatures { 1403 if err := commitSig.ValidateBasic(); err != nil { 1404 return fmt.Errorf("wrong CommitSig #%d: %v", i, err) 1405 } 1406 } 1407 } 1408 1409 return nil 1410 } 1411 1412 // Hash returns the hash of the commit 1413 func (commit *Commit) Hash() tmbytes.HexBytes { 1414 if commit == nil { 1415 return nil 1416 } 1417 if commit.hash == nil { 1418 bs := make([][]byte, len(commit.Signatures)) 1419 for i, commitSig := range commit.Signatures { 1420 bs[i] = cdcEncode(commitSig) 1421 } 1422 commit.hash = merkle.SimpleHashFromByteSlices(bs) 1423 } 1424 return commit.hash 1425 } 1426 1427 // StringIndented returns a string representation of the commit 1428 func (commit *Commit) StringIndented(indent string) string { 1429 if commit == nil { 1430 return "nil-Commit" 1431 } 1432 commitSigStrings := make([]string, len(commit.Signatures)) 1433 for i, commitSig := range commit.Signatures { 1434 commitSigStrings[i] = commitSig.String() 1435 } 1436 return fmt.Sprintf(`Commit{ 1437 %s Height: %d 1438 %s Round: %d 1439 %s BlockID: %v 1440 %s Signatures: 1441 %s %v 1442 %s}#%v`, 1443 indent, commit.Height, 1444 indent, commit.Round, 1445 indent, commit.BlockID, 1446 indent, 1447 indent, strings.Join(commitSigStrings, "\n"+indent+" "), 1448 indent, commit.hash) 1449 } 1450 1451 // ToProto converts Commit to protobuf 1452 func (commit *Commit) ToProto() *tmproto.Commit { 1453 if commit == nil { 1454 return nil 1455 } 1456 1457 c := new(tmproto.Commit) 1458 sigs := make([]tmproto.CommitSig, len(commit.Signatures)) 1459 for i := range commit.Signatures { 1460 sigs[i] = *commit.Signatures[i].ToProto() 1461 } 1462 c.Signatures = sigs 1463 1464 c.Height = commit.Height 1465 c.Round = int32(commit.Round) 1466 c.BlockID = commit.BlockID.ToProto() 1467 if commit.hash != nil { 1468 c.Hash = commit.hash 1469 } 1470 c.BitArray = commit.bitArray.ToProto() 1471 return c 1472 } 1473 1474 // FromProto sets a protobuf Commit to the given pointer. 1475 // It returns an error if the commit is invalid. 1476 func CommitFromProto(cp *tmproto.Commit) (*Commit, error) { 1477 if cp == nil { 1478 return nil, errors.New("nil Commit") 1479 } 1480 1481 var ( 1482 commit = new(Commit) 1483 bitArray *bits.BitArray 1484 ) 1485 1486 bi, err := BlockIDFromProto(&cp.BlockID) 1487 if err != nil { 1488 return nil, err 1489 } 1490 1491 bitArray.FromProto(cp.BitArray) 1492 1493 sigs := make([]CommitSig, len(cp.Signatures)) 1494 for i := range cp.Signatures { 1495 if err := sigs[i].FromProto(cp.Signatures[i]); err != nil { 1496 return nil, err 1497 } 1498 } 1499 commit.Signatures = sigs 1500 1501 commit.Height = cp.Height 1502 commit.Round = int(cp.Round) 1503 commit.BlockID = *bi 1504 commit.hash = cp.Hash 1505 commit.bitArray = bitArray 1506 1507 return commit, commit.ValidateBasic() 1508 } 1509 1510 //----------------------------------------------------------------------------- 1511 1512 // SignedHeader is a header along with the commits that prove it. 1513 // It is the basis of the lite client. 1514 type SignedHeader struct { 1515 *Header `json:"header"` 1516 1517 Commit *Commit `json:"commit"` 1518 } 1519 1520 // ValidateBasic does basic consistency checks and makes sure the header 1521 // and commit are consistent. 1522 // NOTE: This does not actually check the cryptographic signatures. Make 1523 // sure to use a Verifier to validate the signatures actually provide a 1524 // significantly strong proof for this header's validity. 1525 func (sh SignedHeader) ValidateBasic(chainID string) error { 1526 return sh.commonValidateBasic(chainID, false) 1527 } 1528 1529 func (sh SignedHeader) commonValidateBasic(chainID string, isIbc bool) error { 1530 if sh.Header == nil { 1531 return errors.New("missing header") 1532 } 1533 if sh.Commit == nil { 1534 return errors.New("missing commit") 1535 } 1536 1537 if err := sh.Header.ValidateBasic(); err != nil { 1538 return fmt.Errorf("invalid header: %w", err) 1539 } 1540 if err := sh.Commit.ValidateBasic(); err != nil { 1541 return fmt.Errorf("invalid commit: %w", err) 1542 } 1543 1544 if sh.ChainID != chainID { 1545 return fmt.Errorf("header belongs to another chain %q, not %q", sh.ChainID, chainID) 1546 } 1547 1548 // Make sure the header is consistent with the commit. 1549 if sh.Commit.Height != sh.Height { 1550 return fmt.Errorf("header and commit height mismatch: %d vs %d", sh.Height, sh.Commit.Height) 1551 } 1552 1553 var hhash tmbytes.HexBytes 1554 if isIbc { 1555 hhash = sh.PureIBCHash() 1556 } else { 1557 hhash = sh.Hash() 1558 } 1559 if chash := sh.Commit.BlockID.Hash; !bytes.Equal(hhash, chash) { 1560 return fmt.Errorf("commit signs block %X, header is block %X", chash, hhash) 1561 } 1562 return nil 1563 } 1564 1565 func (sh SignedHeader) String() string { 1566 return sh.StringIndented("") 1567 } 1568 1569 // StringIndented returns a string representation of the SignedHeader. 1570 func (sh SignedHeader) StringIndented(indent string) string { 1571 return fmt.Sprintf(`SignedHeader{ 1572 %s %v 1573 %s %v 1574 %s}`, 1575 indent, sh.Header.StringIndented(indent+" "), 1576 indent, sh.Commit.StringIndented(indent+" "), 1577 indent) 1578 } 1579 1580 // ToProto converts SignedHeader to protobuf 1581 func (sh *SignedHeader) ToProto() *tmproto.SignedHeader { 1582 if sh == nil { 1583 return nil 1584 } 1585 1586 psh := new(tmproto.SignedHeader) 1587 if sh.Header != nil { 1588 psh.Header = sh.Header.ToProto() 1589 } 1590 if sh.Commit != nil { 1591 psh.Commit = sh.Commit.ToProto() 1592 } 1593 1594 return psh 1595 } 1596 1597 // FromProto sets a protobuf SignedHeader to the given pointer. 1598 // It returns an error if the hader or the commit is invalid. 1599 func SignedHeaderFromProto(shp *tmproto.SignedHeader) (*SignedHeader, error) { 1600 if shp == nil { 1601 return nil, errors.New("nil SignedHeader") 1602 } 1603 1604 sh := new(SignedHeader) 1605 1606 if shp.Header != nil { 1607 h, err := HeaderFromProto(shp.Header) 1608 if err != nil { 1609 return nil, err 1610 } 1611 sh.Header = &h 1612 } 1613 1614 if shp.Commit != nil { 1615 c, err := CommitFromProto(shp.Commit) 1616 if err != nil { 1617 return nil, err 1618 } 1619 sh.Commit = c 1620 } 1621 1622 return sh, nil 1623 } 1624 1625 //----------------------------------------------------------------------------- 1626 1627 // Data contains the set of transactions included in the block 1628 type Data struct { 1629 1630 // Txs that will be applied by state @ block.Height+1. 1631 // NOTE: not all txs here are valid. We're just agreeing on the order first. 1632 // This means that block.AppHash does not include these txs. 1633 Txs Txs `json:"txs"` 1634 1635 // Volatile 1636 hash tmbytes.HexBytes 1637 } 1638 1639 func (d Data) AminoSize(_ *amino.Codec) int { 1640 var size = 0 1641 1642 for _, tx := range d.Txs { 1643 size += 1 + amino.ByteSliceSize(tx) 1644 } 1645 1646 return size 1647 } 1648 1649 func (d *Data) UnmarshalFromAmino(_ *amino.Codec, data []byte) error { 1650 var dataLen uint64 = 0 1651 var subData []byte 1652 1653 for { 1654 data = data[dataLen:] 1655 if len(data) == 0 { 1656 break 1657 } 1658 1659 pos, pbType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0]) 1660 if err != nil { 1661 return err 1662 } 1663 data = data[1:] 1664 1665 if pbType == amino.Typ3_ByteLength { 1666 var n int 1667 dataLen, n, err = amino.DecodeUvarint(data) 1668 if err != nil { 1669 return err 1670 } 1671 data = data[n:] 1672 if len(data) < int(dataLen) { 1673 return fmt.Errorf("invalid data len") 1674 } 1675 subData = data[:dataLen] 1676 } 1677 1678 switch pos { 1679 case 1: 1680 var tx []byte 1681 if dataLen > 0 { 1682 tx = make([]byte, len(subData)) 1683 copy(tx, subData) 1684 } 1685 d.Txs = append(d.Txs, tx) 1686 default: 1687 return fmt.Errorf("unexpect feild num %d", pos) 1688 } 1689 } 1690 return nil 1691 } 1692 1693 // Hash returns the hash of the data 1694 func (data *Data) Hash(height int64) tmbytes.HexBytes { 1695 if data == nil { 1696 return (Txs{}).Hash(height) 1697 } 1698 if data.hash == nil { 1699 data.hash = data.Txs.Hash(height) // NOTE: leaves of merkle tree are TxIDs 1700 } 1701 return data.hash 1702 } 1703 1704 // StringIndented returns a string representation of the transactions 1705 func (data *Data) StringIndented(indent string, height int64) string { 1706 if data == nil { 1707 return "nil-Data" 1708 } 1709 txStrings := make([]string, tmmath.MinInt(len(data.Txs), 21)) 1710 for i, tx := range data.Txs { 1711 if i == 20 { 1712 txStrings[i] = fmt.Sprintf("... (%v total)", len(data.Txs)) 1713 break 1714 } 1715 txStrings[i] = fmt.Sprintf("%X (%d bytes)", tx.Hash(height), len(tx)) 1716 } 1717 return fmt.Sprintf(`Data{ 1718 %s %v 1719 %s}#%v`, 1720 indent, strings.Join(txStrings, "\n"+indent+" "), 1721 indent, data.hash) 1722 } 1723 1724 //----------------------------------------------------------------------------- 1725 1726 // EvidenceData contains any evidence of malicious wrong-doing by validators 1727 type EvidenceData struct { 1728 Evidence EvidenceList `json:"evidence"` 1729 1730 // Volatile 1731 hash tmbytes.HexBytes 1732 } 1733 1734 func (d EvidenceData) AminoSize(cdc *amino.Codec) int { 1735 var size = 0 1736 1737 for _, ev := range d.Evidence { 1738 if ev != nil { 1739 var evSize int 1740 if sizer, ok := ev.(amino.Sizer); ok { 1741 evSize = 4 + sizer.AminoSize(cdc) 1742 } else { 1743 evSize = len(cdc.MustMarshalBinaryBare(ev)) 1744 } 1745 size += 1 + amino.UvarintSize(uint64(evSize)) + evSize 1746 } else { 1747 size += 1 + amino.UvarintSize(0) 1748 } 1749 } 1750 1751 return size 1752 } 1753 1754 func (d *EvidenceData) UnmarshalFromAmino(cdc *amino.Codec, data []byte) error { 1755 var dataLen uint64 = 0 1756 var subData []byte 1757 1758 for { 1759 data = data[dataLen:] 1760 if len(data) == 0 { 1761 break 1762 } 1763 1764 pos, pbType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0]) 1765 if err != nil { 1766 return err 1767 } 1768 data = data[1:] 1769 1770 if pbType == amino.Typ3_ByteLength { 1771 var n int 1772 dataLen, n, err = amino.DecodeUvarint(data) 1773 if err != nil { 1774 return err 1775 } 1776 data = data[n:] 1777 if len(data) < int(dataLen) { 1778 return fmt.Errorf("invalid data len") 1779 } 1780 subData = data[:dataLen] 1781 } else { 1782 return fmt.Errorf("unexpect pb type %d", pbType) 1783 } 1784 1785 switch pos { 1786 case 1: 1787 var evi Evidence 1788 if dataLen == 0 { 1789 d.Evidence = append(d.Evidence, nil) 1790 } else { 1791 eviTmp, err := cdc.UnmarshalBinaryBareWithRegisteredUnmarshaller(subData, &evi) 1792 if err != nil { 1793 err = cdc.UnmarshalBinaryBare(subData, &evi) 1794 if err != nil { 1795 return err 1796 } else { 1797 d.Evidence = append(d.Evidence, evi) 1798 } 1799 } else { 1800 d.Evidence = append(d.Evidence, eviTmp.(Evidence)) 1801 } 1802 } 1803 default: 1804 return fmt.Errorf("unexpect feild num %d", pos) 1805 } 1806 } 1807 return nil 1808 } 1809 1810 // Hash returns the hash of the data. 1811 func (data *EvidenceData) Hash() tmbytes.HexBytes { 1812 if data.hash == nil { 1813 data.hash = data.Evidence.Hash() 1814 } 1815 return data.hash 1816 } 1817 1818 // StringIndented returns a string representation of the evidence. 1819 func (data *EvidenceData) StringIndented(indent string) string { 1820 if data == nil { 1821 return "nil-Evidence" 1822 } 1823 evStrings := make([]string, tmmath.MinInt(len(data.Evidence), 21)) 1824 for i, ev := range data.Evidence { 1825 if i == 20 { 1826 evStrings[i] = fmt.Sprintf("... (%v total)", len(data.Evidence)) 1827 break 1828 } 1829 evStrings[i] = fmt.Sprintf("Evidence:%v", ev) 1830 } 1831 return fmt.Sprintf(`EvidenceData{ 1832 %s %v 1833 %s}#%v`, 1834 indent, strings.Join(evStrings, "\n"+indent+" "), 1835 indent, data.hash) 1836 } 1837 1838 //-------------------------------------------------------------------------------- 1839 1840 // BlockID defines the unique ID of a block as its Hash and its PartSetHeader 1841 type BlockID struct { 1842 Hash tmbytes.HexBytes `json:"hash"` 1843 PartsHeader PartSetHeader `json:"parts"` 1844 } 1845 1846 func (blockID BlockID) AminoSize(_ *amino.Codec) int { 1847 var size int 1848 if len(blockID.Hash) > 0 { 1849 size += 1 + amino.UvarintSize(uint64(len(blockID.Hash))) + len(blockID.Hash) 1850 } 1851 headerSize := blockID.PartsHeader.AminoSize() 1852 if headerSize > 0 { 1853 size += 1 + amino.UvarintSize(uint64(headerSize)) + headerSize 1854 } 1855 return size 1856 } 1857 1858 func (blockID *BlockID) UnmarshalFromAmino(cdc *amino.Codec, data []byte) error { 1859 var dataLen uint64 = 0 1860 var subData []byte 1861 1862 for { 1863 data = data[dataLen:] 1864 1865 if len(data) == 0 { 1866 break 1867 } 1868 1869 pos, aminoType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0]) 1870 if err != nil { 1871 return err 1872 } 1873 data = data[1:] 1874 1875 if aminoType == amino.Typ3_ByteLength { 1876 var n int 1877 dataLen, n, err = amino.DecodeUvarint(data) 1878 if err != nil { 1879 return err 1880 } 1881 1882 data = data[n:] 1883 if len(data) < int(dataLen) { 1884 return fmt.Errorf("invalid data len") 1885 } 1886 subData = data[:dataLen] 1887 } 1888 1889 switch pos { 1890 case 1: 1891 blockID.Hash = make([]byte, len(subData)) 1892 copy(blockID.Hash, subData) 1893 case 2: 1894 err = blockID.PartsHeader.UnmarshalFromAmino(cdc, subData) 1895 if err != nil { 1896 return err 1897 } 1898 default: 1899 return fmt.Errorf("unexpect feild num %d", pos) 1900 } 1901 } 1902 return nil 1903 } 1904 1905 // Equals returns true if the BlockID matches the given BlockID 1906 func (blockID BlockID) Equals(other BlockID) bool { 1907 return bytes.Equal(blockID.Hash, other.Hash) && 1908 blockID.PartsHeader.Equals(other.PartsHeader) 1909 } 1910 1911 // Key returns a machine-readable string representation of the BlockID 1912 func (blockID BlockID) Key() string { 1913 bz, err := cdc.MarshalBinaryBare(blockID.PartsHeader) 1914 if err != nil { 1915 panic(err) 1916 } 1917 return string(blockID.Hash) + string(bz) 1918 } 1919 1920 // ValidateBasic performs basic validation. 1921 func (blockID BlockID) ValidateBasic() error { 1922 // Hash can be empty in case of POLBlockID in Proposal. 1923 if err := ValidateHash(blockID.Hash); err != nil { 1924 return fmt.Errorf("wrong Hash") 1925 } 1926 if err := blockID.PartsHeader.ValidateBasic(); err != nil { 1927 return fmt.Errorf("wrong PartsHeader: %v", err) 1928 } 1929 return nil 1930 } 1931 1932 // IsZero returns true if this is the BlockID of a nil block. 1933 func (blockID BlockID) IsZero() bool { 1934 return len(blockID.Hash) == 0 && 1935 blockID.PartsHeader.IsZero() 1936 } 1937 1938 // IsComplete returns true if this is a valid BlockID of a non-nil block. 1939 func (blockID BlockID) IsComplete() bool { 1940 return len(blockID.Hash) == tmhash.Size && 1941 blockID.PartsHeader.Total > 0 && 1942 len(blockID.PartsHeader.Hash) == tmhash.Size 1943 } 1944 1945 // String returns a human readable string representation of the BlockID 1946 func (blockID BlockID) String() string { 1947 return fmt.Sprintf(`%v:%v`, blockID.Hash, blockID.PartsHeader) 1948 } 1949 1950 // ToProto converts BlockID to protobuf 1951 func (blockID *BlockID) ToProto() tmproto.BlockID { 1952 if blockID == nil { 1953 return tmproto.BlockID{} 1954 } 1955 1956 return tmproto.BlockID{ 1957 Hash: blockID.Hash, 1958 PartsHeader: blockID.PartsHeader.ToProto(), 1959 } 1960 } 1961 1962 func (blockID *BlockID) ToIBCProto() tmproto.BlockID { 1963 if blockID == nil { 1964 return tmproto.BlockID{} 1965 } 1966 return tmproto.BlockID{ 1967 Hash: blockID.Hash, 1968 PartsHeader: blockID.PartsHeader.ToIBCProto(), 1969 } 1970 } 1971 1972 // FromProto sets a protobuf BlockID to the given pointer. 1973 // It returns an error if the block id is invalid. 1974 func BlockIDFromProto(bID *tmproto.BlockID) (*BlockID, error) { 1975 if bID == nil { 1976 return nil, errors.New("nil BlockID") 1977 } 1978 blockID := new(BlockID) 1979 ph, err := PartSetHeaderFromProto(&bID.PartsHeader) 1980 if err != nil { 1981 return nil, err 1982 } 1983 1984 blockID.PartsHeader = *ph 1985 blockID.Hash = bID.Hash 1986 1987 return blockID, blockID.ValidateBasic() 1988 }