github.com/adoriasoft/tendermint@v0.34.0-dev1.0.20200722151356-96d84601a75a/types/block.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "strings" 8 "time" 9 10 "github.com/gogo/protobuf/proto" 11 gogotypes "github.com/gogo/protobuf/types" 12 13 "github.com/tendermint/tendermint/crypto" 14 "github.com/tendermint/tendermint/crypto/merkle" 15 "github.com/tendermint/tendermint/crypto/tmhash" 16 "github.com/tendermint/tendermint/libs/bits" 17 tmbytes "github.com/tendermint/tendermint/libs/bytes" 18 tmmath "github.com/tendermint/tendermint/libs/math" 19 tmsync "github.com/tendermint/tendermint/libs/sync" 20 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 21 tmversion "github.com/tendermint/tendermint/proto/tendermint/version" 22 ) 23 24 const ( 25 // MaxHeaderBytes is a maximum header size. 26 MaxHeaderBytes int64 = 626 27 28 // MaxOverheadForBlock - maximum overhead to encode a block (up to 29 // MaxBlockSizeBytes in size) not including it's parts except Data. 30 // This means it also excludes the overhead for individual transactions. 31 // 32 // Uvarint length of MaxBlockSizeBytes: 4 bytes 33 // 2 fields (2 embedded): 2 bytes 34 // Uvarint length of Data.Txs: 4 bytes 35 // Data.Txs field: 1 byte 36 MaxOverheadForBlock int64 = 11 37 ) 38 39 // Block defines the atomic unit of a Tendermint blockchain. 40 type Block struct { 41 mtx tmsync.Mutex 42 43 Header `json:"header"` 44 Data `json:"data"` 45 Evidence EvidenceData `json:"evidence"` 46 LastCommit *Commit `json:"last_commit"` 47 } 48 49 // ValidateBasic performs basic validation that doesn't involve state data. 50 // It checks the internal consistency of the block. 51 // Further validation is done using state#ValidateBlock. 52 func (b *Block) ValidateBasic() error { 53 if b == nil { 54 return errors.New("nil block") 55 } 56 57 b.mtx.Lock() 58 defer b.mtx.Unlock() 59 60 if err := b.Header.ValidateBasic(); err != nil { 61 return fmt.Errorf("invalid header: %w", err) 62 } 63 64 // Validate the last commit and its hash. 65 if b.LastCommit == nil { 66 return errors.New("nil LastCommit") 67 } 68 if b.Header.Height > 1 { 69 if err := b.LastCommit.ValidateBasic(); err != nil { 70 return fmt.Errorf("wrong LastCommit: %v", err) 71 } 72 } 73 74 if !bytes.Equal(b.LastCommitHash, b.LastCommit.Hash()) { 75 return fmt.Errorf("wrong Header.LastCommitHash. Expected %v, got %v", 76 b.LastCommit.Hash(), 77 b.LastCommitHash, 78 ) 79 } 80 81 // NOTE: b.Data.Txs may be nil, but b.Data.Hash() still works fine. 82 if !bytes.Equal(b.DataHash, b.Data.Hash()) { 83 return fmt.Errorf( 84 "wrong Header.DataHash. Expected %v, got %v", 85 b.Data.Hash(), 86 b.DataHash, 87 ) 88 } 89 90 // NOTE: b.Evidence.Evidence may be nil, but we're just looping. 91 for i, ev := range b.Evidence.Evidence { 92 switch ev.(type) { 93 case *ConflictingHeadersEvidence: 94 // ConflictingHeadersEvidence must be broken up in pieces and never 95 // committed as a single piece. 96 return fmt.Errorf("found ConflictingHeadersEvidence (#%d)", i) 97 case *PotentialAmnesiaEvidence: 98 // PotentialAmnesiaEvidence does not contribute to anything on its own, so 99 // reject it as well. 100 return fmt.Errorf("found PotentialAmnesiaEvidence (#%d)", i) 101 } 102 103 if err := ev.ValidateBasic(); err != nil { 104 return fmt.Errorf("invalid evidence (#%d): %v", i, err) 105 } 106 } 107 108 if !bytes.Equal(b.EvidenceHash, b.Evidence.Hash()) { 109 return fmt.Errorf("wrong Header.EvidenceHash. Expected %v, got %v", 110 b.EvidenceHash, 111 b.Evidence.Hash(), 112 ) 113 } 114 115 return nil 116 } 117 118 // fillHeader fills in any remaining header fields that are a function of the block data 119 func (b *Block) fillHeader() { 120 if b.LastCommitHash == nil { 121 b.LastCommitHash = b.LastCommit.Hash() 122 } 123 if b.DataHash == nil { 124 b.DataHash = b.Data.Hash() 125 } 126 if b.EvidenceHash == nil { 127 b.EvidenceHash = b.Evidence.Hash() 128 } 129 } 130 131 // Hash computes and returns the block hash. 132 // If the block is incomplete, block hash is nil for safety. 133 func (b *Block) Hash() tmbytes.HexBytes { 134 if b == nil { 135 return nil 136 } 137 b.mtx.Lock() 138 defer b.mtx.Unlock() 139 140 if b.LastCommit == nil { 141 return nil 142 } 143 b.fillHeader() 144 return b.Header.Hash() 145 } 146 147 // MakePartSet returns a PartSet containing parts of a serialized block. 148 // This is the form in which the block is gossipped to peers. 149 // CONTRACT: partSize is greater than zero. 150 func (b *Block) MakePartSet(partSize uint32) *PartSet { 151 if b == nil { 152 return nil 153 } 154 b.mtx.Lock() 155 defer b.mtx.Unlock() 156 157 pbb, err := b.ToProto() 158 if err != nil { 159 panic(err) 160 } 161 bz, err := proto.Marshal(pbb) 162 if err != nil { 163 panic(err) 164 } 165 return NewPartSetFromData(bz, partSize) 166 } 167 168 // HashesTo is a convenience function that checks if a block hashes to the given argument. 169 // Returns false if the block is nil or the hash is empty. 170 func (b *Block) HashesTo(hash []byte) bool { 171 if len(hash) == 0 { 172 return false 173 } 174 if b == nil { 175 return false 176 } 177 return bytes.Equal(b.Hash(), hash) 178 } 179 180 // Size returns size of the block in bytes. 181 func (b *Block) Size() int { 182 pbb, err := b.ToProto() 183 if err != nil { 184 return 0 185 } 186 187 return pbb.Size() 188 } 189 190 // String returns a string representation of the block 191 func (b *Block) String() string { 192 return b.StringIndented("") 193 } 194 195 // StringIndented returns a string representation of the block 196 func (b *Block) StringIndented(indent string) string { 197 if b == nil { 198 return "nil-Block" 199 } 200 return fmt.Sprintf(`Block{ 201 %s %v 202 %s %v 203 %s %v 204 %s %v 205 %s}#%v`, 206 indent, b.Header.StringIndented(indent+" "), 207 indent, b.Data.StringIndented(indent+" "), 208 indent, b.Evidence.StringIndented(indent+" "), 209 indent, b.LastCommit.StringIndented(indent+" "), 210 indent, b.Hash()) 211 } 212 213 // StringShort returns a shortened string representation of the block 214 func (b *Block) StringShort() string { 215 if b == nil { 216 return "nil-Block" 217 } 218 return fmt.Sprintf("Block#%v", b.Hash()) 219 } 220 221 // ToProto converts Block to protobuf 222 func (b *Block) ToProto() (*tmproto.Block, error) { 223 if b == nil { 224 return nil, errors.New("nil Block") 225 } 226 227 pb := new(tmproto.Block) 228 229 pb.Header = *b.Header.ToProto() 230 pb.LastCommit = b.LastCommit.ToProto() 231 pb.Data = b.Data.ToProto() 232 233 protoEvidence, err := b.Evidence.ToProto() 234 if err != nil { 235 return nil, err 236 } 237 pb.Evidence = *protoEvidence 238 239 return pb, nil 240 } 241 242 // FromProto sets a protobuf Block to the given pointer. 243 // It returns an error if the block is invalid. 244 func BlockFromProto(bp *tmproto.Block) (*Block, error) { 245 if bp == nil { 246 return nil, errors.New("nil block") 247 } 248 249 b := new(Block) 250 h, err := HeaderFromProto(&bp.Header) 251 if err != nil { 252 return nil, err 253 } 254 b.Header = h 255 data, err := DataFromProto(&bp.Data) 256 if err != nil { 257 return nil, err 258 } 259 b.Data = data 260 b.Evidence.FromProto(&bp.Evidence) 261 262 if bp.LastCommit != nil { 263 lc, err := CommitFromProto(bp.LastCommit) 264 if err != nil { 265 return nil, err 266 } 267 b.LastCommit = lc 268 } 269 270 return b, b.ValidateBasic() 271 } 272 273 //----------------------------------------------------------------------------- 274 275 // MaxDataBytes returns the maximum size of block's data. 276 // 277 // XXX: Panics on negative result. 278 func MaxDataBytes(maxBytes int64, valsCount, evidenceCount int) int64 { 279 maxDataBytes := maxBytes - 280 MaxOverheadForBlock - 281 MaxHeaderBytes - 282 int64(valsCount)*MaxVoteBytes - 283 int64(evidenceCount)*MaxEvidenceBytes 284 285 if maxDataBytes < 0 { 286 panic(fmt.Sprintf( 287 "Negative MaxDataBytes. Block.MaxBytes=%d is too small to accommodate header&lastCommit&evidence=%d", 288 maxBytes, 289 -(maxDataBytes - maxBytes), 290 )) 291 } 292 293 return maxDataBytes 294 295 } 296 297 // MaxDataBytesUnknownEvidence returns the maximum size of block's data when 298 // evidence count is unknown. MaxEvidencePerBlock will be used for the size 299 // of evidence. 300 // 301 // XXX: Panics on negative result. 302 func MaxDataBytesUnknownEvidence(maxBytes int64, valsCount int, maxNumEvidence uint32) int64 { 303 maxEvidenceBytes := int64(maxNumEvidence) * MaxEvidenceBytes 304 maxDataBytes := maxBytes - 305 MaxOverheadForBlock - 306 MaxHeaderBytes - 307 int64(valsCount)*MaxVoteBytes - 308 maxEvidenceBytes 309 310 if maxDataBytes < 0 { 311 panic(fmt.Sprintf( 312 "Negative MaxDataBytesUnknownEvidence. Block.MaxBytes=%d is too small to accommodate header&lastCommit&evidence=%d", 313 maxBytes, 314 -(maxDataBytes - maxBytes), 315 )) 316 } 317 318 return maxDataBytes 319 } 320 321 //----------------------------------------------------------------------------- 322 323 // Header defines the structure of a Tendermint block header. 324 // NOTE: changes to the Header should be duplicated in: 325 // - header.Hash() 326 // - abci.Header 327 // - https://github.com/tendermint/spec/blob/master/spec/blockchain/blockchain.md 328 type Header struct { 329 // basic block info 330 Version tmversion.Consensus `json:"version"` 331 ChainID string `json:"chain_id"` 332 Height int64 `json:"height"` 333 Time time.Time `json:"time"` 334 335 // prev block info 336 LastBlockID BlockID `json:"last_block_id"` 337 338 // hashes of block data 339 LastCommitHash tmbytes.HexBytes `json:"last_commit_hash"` // commit from validators from the last block 340 DataHash tmbytes.HexBytes `json:"data_hash"` // transactions 341 342 // hashes from the app output from the prev block 343 ValidatorsHash tmbytes.HexBytes `json:"validators_hash"` // validators for the current block 344 NextValidatorsHash tmbytes.HexBytes `json:"next_validators_hash"` // validators for the next block 345 ConsensusHash tmbytes.HexBytes `json:"consensus_hash"` // consensus params for current block 346 AppHash tmbytes.HexBytes `json:"app_hash"` // state after txs from the previous block 347 // root hash of all results from the txs from the previous block 348 LastResultsHash tmbytes.HexBytes `json:"last_results_hash"` 349 350 // consensus info 351 EvidenceHash tmbytes.HexBytes `json:"evidence_hash"` // evidence included in the block 352 ProposerAddress Address `json:"proposer_address"` // original proposer of the block 353 } 354 355 // Populate the Header with state-derived data. 356 // Call this after MakeBlock to complete the Header. 357 func (h *Header) Populate( 358 version tmversion.Consensus, chainID string, 359 timestamp time.Time, lastBlockID BlockID, 360 valHash, nextValHash []byte, 361 consensusHash, appHash, lastResultsHash []byte, 362 proposerAddress Address, 363 ) { 364 h.Version = version 365 h.ChainID = chainID 366 h.Time = timestamp 367 h.LastBlockID = lastBlockID 368 h.ValidatorsHash = valHash 369 h.NextValidatorsHash = nextValHash 370 h.ConsensusHash = consensusHash 371 h.AppHash = appHash 372 h.LastResultsHash = lastResultsHash 373 h.ProposerAddress = proposerAddress 374 } 375 376 // ValidateBasic performs stateless validation on a Header returning an error 377 // if any validation fails. 378 // 379 // NOTE: Timestamp validation is subtle and handled elsewhere. 380 func (h Header) ValidateBasic() error { 381 if len(h.ChainID) > MaxChainIDLen { 382 return fmt.Errorf("chainID is too long; got: %d, max: %d", len(h.ChainID), MaxChainIDLen) 383 } 384 385 if h.Height < 0 { 386 return errors.New("negative Height") 387 } else if h.Height == 0 { 388 return errors.New("zero Height") 389 } 390 391 if err := h.LastBlockID.ValidateBasic(); err != nil { 392 return fmt.Errorf("wrong LastBlockID: %w", err) 393 } 394 395 if err := ValidateHash(h.LastCommitHash); err != nil { 396 return fmt.Errorf("wrong LastCommitHash: %v", err) 397 } 398 399 if err := ValidateHash(h.DataHash); err != nil { 400 return fmt.Errorf("wrong DataHash: %v", err) 401 } 402 403 if err := ValidateHash(h.EvidenceHash); err != nil { 404 return fmt.Errorf("wrong EvidenceHash: %v", err) 405 } 406 407 if len(h.ProposerAddress) != crypto.AddressSize { 408 return fmt.Errorf( 409 "invalid ProposerAddress length; got: %d, expected: %d", 410 len(h.ProposerAddress), crypto.AddressSize, 411 ) 412 } 413 414 // Basic validation of hashes related to application data. 415 // Will validate fully against state in state#ValidateBlock. 416 if err := ValidateHash(h.ValidatorsHash); err != nil { 417 return fmt.Errorf("wrong ValidatorsHash: %v", err) 418 } 419 if err := ValidateHash(h.NextValidatorsHash); err != nil { 420 return fmt.Errorf("wrong NextValidatorsHash: %v", err) 421 } 422 if err := ValidateHash(h.ConsensusHash); err != nil { 423 return fmt.Errorf("wrong ConsensusHash: %v", err) 424 } 425 // NOTE: AppHash is arbitrary length 426 if err := ValidateHash(h.LastResultsHash); err != nil { 427 return fmt.Errorf("wrong LastResultsHash: %v", err) 428 } 429 430 return nil 431 } 432 433 // Hash returns the hash of the header. 434 // It computes a Merkle tree from the header fields 435 // ordered as they appear in the Header. 436 // Returns nil if ValidatorHash is missing, 437 // since a Header is not valid unless there is 438 // a ValidatorsHash (corresponding to the validator set). 439 func (h *Header) Hash() tmbytes.HexBytes { 440 if h == nil || len(h.ValidatorsHash) == 0 { 441 return nil 442 } 443 hbz, err := h.Version.Marshal() 444 if err != nil { 445 return nil 446 } 447 448 pbt, err := gogotypes.StdTimeMarshal(h.Time) 449 if err != nil { 450 return nil 451 } 452 453 pbbi := h.LastBlockID.ToProto() 454 bzbi, err := pbbi.Marshal() 455 if err != nil { 456 return nil 457 } 458 return merkle.HashFromByteSlices([][]byte{ 459 hbz, 460 cdcEncode(h.ChainID), 461 cdcEncode(h.Height), 462 pbt, 463 bzbi, 464 cdcEncode(h.LastCommitHash), 465 cdcEncode(h.DataHash), 466 cdcEncode(h.ValidatorsHash), 467 cdcEncode(h.NextValidatorsHash), 468 cdcEncode(h.ConsensusHash), 469 cdcEncode(h.AppHash), 470 cdcEncode(h.LastResultsHash), 471 cdcEncode(h.EvidenceHash), 472 cdcEncode(h.ProposerAddress), 473 }) 474 } 475 476 // StringIndented returns a string representation of the header 477 func (h *Header) StringIndented(indent string) string { 478 if h == nil { 479 return "nil-Header" 480 } 481 return fmt.Sprintf(`Header{ 482 %s Version: %v 483 %s ChainID: %v 484 %s Height: %v 485 %s Time: %v 486 %s LastBlockID: %v 487 %s LastCommit: %v 488 %s Data: %v 489 %s Validators: %v 490 %s NextValidators: %v 491 %s App: %v 492 %s Consensus: %v 493 %s Results: %v 494 %s Evidence: %v 495 %s Proposer: %v 496 %s}#%v`, 497 indent, h.Version, 498 indent, h.ChainID, 499 indent, h.Height, 500 indent, h.Time, 501 indent, h.LastBlockID, 502 indent, h.LastCommitHash, 503 indent, h.DataHash, 504 indent, h.ValidatorsHash, 505 indent, h.NextValidatorsHash, 506 indent, h.AppHash, 507 indent, h.ConsensusHash, 508 indent, h.LastResultsHash, 509 indent, h.EvidenceHash, 510 indent, h.ProposerAddress, 511 indent, h.Hash()) 512 } 513 514 // ToProto converts Header to protobuf 515 func (h *Header) ToProto() *tmproto.Header { 516 if h == nil { 517 return nil 518 } 519 520 return &tmproto.Header{ 521 Version: h.Version, 522 ChainID: h.ChainID, 523 Height: h.Height, 524 Time: h.Time, 525 LastBlockId: h.LastBlockID.ToProto(), 526 ValidatorsHash: h.ValidatorsHash, 527 NextValidatorsHash: h.NextValidatorsHash, 528 ConsensusHash: h.ConsensusHash, 529 AppHash: h.AppHash, 530 DataHash: h.DataHash, 531 EvidenceHash: h.EvidenceHash, 532 LastResultsHash: h.LastResultsHash, 533 LastCommitHash: h.LastCommitHash, 534 ProposerAddress: h.ProposerAddress, 535 } 536 } 537 538 // FromProto sets a protobuf Header to the given pointer. 539 // It returns an error if the header is invalid. 540 func HeaderFromProto(ph *tmproto.Header) (Header, error) { 541 if ph == nil { 542 return Header{}, errors.New("nil Header") 543 } 544 545 h := new(Header) 546 547 bi, err := BlockIDFromProto(&ph.LastBlockId) 548 if err != nil { 549 return Header{}, err 550 } 551 552 h.Version = ph.Version 553 h.ChainID = ph.ChainID 554 h.Height = ph.Height 555 h.Time = ph.Time 556 h.Height = ph.Height 557 h.LastBlockID = *bi 558 h.ValidatorsHash = ph.ValidatorsHash 559 h.NextValidatorsHash = ph.NextValidatorsHash 560 h.ConsensusHash = ph.ConsensusHash 561 h.AppHash = ph.AppHash 562 h.DataHash = ph.DataHash 563 h.EvidenceHash = ph.EvidenceHash 564 h.LastResultsHash = ph.LastResultsHash 565 h.LastCommitHash = ph.LastCommitHash 566 h.ProposerAddress = ph.ProposerAddress 567 568 return *h, h.ValidateBasic() 569 } 570 571 //------------------------------------- 572 573 // BlockIDFlag indicates which BlockID the signature is for. 574 type BlockIDFlag byte 575 576 const ( 577 // BlockIDFlagAbsent - no vote was received from a validator. 578 BlockIDFlagAbsent BlockIDFlag = iota + 1 579 // BlockIDFlagCommit - voted for the Commit.BlockID. 580 BlockIDFlagCommit 581 // BlockIDFlagNil - voted for nil. 582 BlockIDFlagNil 583 ) 584 585 // CommitSig is a part of the Vote included in a Commit. 586 type CommitSig struct { 587 BlockIDFlag BlockIDFlag `json:"block_id_flag"` 588 ValidatorAddress Address `json:"validator_address"` 589 Timestamp time.Time `json:"timestamp"` 590 Signature []byte `json:"signature"` 591 } 592 593 // NewCommitSigForBlock returns new CommitSig with BlockIDFlagCommit. 594 func NewCommitSigForBlock(signature []byte, valAddr Address, ts time.Time) CommitSig { 595 return CommitSig{ 596 BlockIDFlag: BlockIDFlagCommit, 597 ValidatorAddress: valAddr, 598 Timestamp: ts, 599 Signature: signature, 600 } 601 } 602 603 // ForBlock returns true if CommitSig is for the block. 604 func (cs CommitSig) ForBlock() bool { 605 return cs.BlockIDFlag == BlockIDFlagCommit 606 } 607 608 // NewCommitSigAbsent returns new CommitSig with BlockIDFlagAbsent. Other 609 // fields are all empty. 610 func NewCommitSigAbsent() CommitSig { 611 return CommitSig{ 612 BlockIDFlag: BlockIDFlagAbsent, 613 } 614 } 615 616 // Absent returns true if CommitSig is absent. 617 func (cs CommitSig) Absent() bool { 618 return cs.BlockIDFlag == BlockIDFlagAbsent 619 } 620 621 func (cs CommitSig) String() string { 622 return fmt.Sprintf("CommitSig{%X by %X on %v @ %s}", 623 tmbytes.Fingerprint(cs.Signature), 624 tmbytes.Fingerprint(cs.ValidatorAddress), 625 cs.BlockIDFlag, 626 CanonicalTime(cs.Timestamp)) 627 } 628 629 // BlockID returns the Commit's BlockID if CommitSig indicates signing, 630 // otherwise - empty BlockID. 631 func (cs CommitSig) BlockID(commitBlockID BlockID) BlockID { 632 var blockID BlockID 633 switch cs.BlockIDFlag { 634 case BlockIDFlagAbsent: 635 blockID = BlockID{} 636 case BlockIDFlagCommit: 637 blockID = commitBlockID 638 case BlockIDFlagNil: 639 blockID = BlockID{} 640 default: 641 panic(fmt.Sprintf("Unknown BlockIDFlag: %v", cs.BlockIDFlag)) 642 } 643 return blockID 644 } 645 646 // ValidateBasic performs basic validation. 647 func (cs CommitSig) ValidateBasic() error { 648 switch cs.BlockIDFlag { 649 case BlockIDFlagAbsent: 650 case BlockIDFlagCommit: 651 case BlockIDFlagNil: 652 default: 653 return fmt.Errorf("unknown BlockIDFlag: %v", cs.BlockIDFlag) 654 } 655 656 switch cs.BlockIDFlag { 657 case BlockIDFlagAbsent: 658 if len(cs.ValidatorAddress) != 0 { 659 return errors.New("validator address is present") 660 } 661 if !cs.Timestamp.IsZero() { 662 return errors.New("time is present") 663 } 664 if len(cs.Signature) != 0 { 665 return errors.New("signature is present") 666 } 667 default: 668 if len(cs.ValidatorAddress) != crypto.AddressSize { 669 return fmt.Errorf("expected ValidatorAddress size to be %d bytes, got %d bytes", 670 crypto.AddressSize, 671 len(cs.ValidatorAddress), 672 ) 673 } 674 // NOTE: Timestamp validation is subtle and handled elsewhere. 675 if len(cs.Signature) == 0 { 676 return errors.New("signature is missing") 677 } 678 if len(cs.Signature) > MaxSignatureSize { 679 return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize) 680 } 681 } 682 683 return nil 684 } 685 686 // ToProto converts CommitSig to protobuf 687 func (cs *CommitSig) ToProto() *tmproto.CommitSig { 688 if cs == nil { 689 return nil 690 } 691 692 return &tmproto.CommitSig{ 693 BlockIdFlag: tmproto.BlockIDFlag(cs.BlockIDFlag), 694 ValidatorAddress: cs.ValidatorAddress, 695 Timestamp: cs.Timestamp, 696 Signature: cs.Signature, 697 } 698 } 699 700 // FromProto sets a protobuf CommitSig to the given pointer. 701 // It returns an error if the CommitSig is invalid. 702 func (cs *CommitSig) FromProto(csp tmproto.CommitSig) error { 703 704 cs.BlockIDFlag = BlockIDFlag(csp.BlockIdFlag) 705 cs.ValidatorAddress = csp.ValidatorAddress 706 cs.Timestamp = csp.Timestamp 707 cs.Signature = csp.Signature 708 709 return cs.ValidateBasic() 710 } 711 712 //------------------------------------- 713 714 // Commit contains the evidence that a block was committed by a set of validators. 715 // NOTE: Commit is empty for height 1, but never nil. 716 type Commit struct { 717 // NOTE: The signatures are in order of address to preserve the bonded 718 // ValidatorSet order. 719 // Any peer with a block can gossip signatures by index with a peer without 720 // recalculating the active ValidatorSet. 721 Height int64 `json:"height"` 722 Round int32 `json:"round"` 723 BlockID BlockID `json:"block_id"` 724 Signatures []CommitSig `json:"signatures"` 725 726 // Memoized in first call to corresponding method. 727 // NOTE: can't memoize in constructor because constructor isn't used for 728 // unmarshaling. 729 hash tmbytes.HexBytes 730 bitArray *bits.BitArray 731 } 732 733 // NewCommit returns a new Commit. 734 func NewCommit(height int64, round int32, blockID BlockID, commitSigs []CommitSig) *Commit { 735 return &Commit{ 736 Height: height, 737 Round: round, 738 BlockID: blockID, 739 Signatures: commitSigs, 740 } 741 } 742 743 // CommitToVoteSet constructs a VoteSet from the Commit and validator set. 744 // Panics if signatures from the commit can't be added to the voteset. 745 // Inverse of VoteSet.MakeCommit(). 746 func CommitToVoteSet(chainID string, commit *Commit, vals *ValidatorSet) *VoteSet { 747 voteSet := NewVoteSet(chainID, commit.Height, commit.Round, tmproto.PrecommitType, vals) 748 for idx, commitSig := range commit.Signatures { 749 if commitSig.Absent() { 750 continue // OK, some precommits can be missing. 751 } 752 added, err := voteSet.AddVote(commit.GetVote(int32(idx))) 753 if !added || err != nil { 754 panic(fmt.Sprintf("Failed to reconstruct LastCommit: %v", err)) 755 } 756 } 757 return voteSet 758 } 759 760 // GetVote converts the CommitSig for the given valIdx to a Vote. 761 // Returns nil if the precommit at valIdx is nil. 762 // Panics if valIdx >= commit.Size(). 763 func (commit *Commit) GetVote(valIdx int32) *Vote { 764 commitSig := commit.Signatures[valIdx] 765 return &Vote{ 766 Type: tmproto.PrecommitType, 767 Height: commit.Height, 768 Round: commit.Round, 769 BlockID: commitSig.BlockID(commit.BlockID), 770 Timestamp: commitSig.Timestamp, 771 ValidatorAddress: commitSig.ValidatorAddress, 772 ValidatorIndex: valIdx, 773 Signature: commitSig.Signature, 774 } 775 } 776 777 // VoteSignBytes returns the bytes of the Vote corresponding to valIdx for 778 // signing. 779 // 780 // The only unique part is the Timestamp - all other fields signed over are 781 // otherwise the same for all validators. 782 // 783 // Panics if valIdx >= commit.Size(). 784 // 785 // See VoteSignBytes 786 func (commit *Commit) VoteSignBytes(chainID string, valIdx int32) []byte { 787 v := commit.GetVote(valIdx).ToProto() 788 return VoteSignBytes(chainID, v) 789 } 790 791 // Type returns the vote type of the commit, which is always VoteTypePrecommit 792 // Implements VoteSetReader. 793 func (commit *Commit) Type() byte { 794 return byte(tmproto.PrecommitType) 795 } 796 797 // GetHeight returns height of the commit. 798 // Implements VoteSetReader. 799 func (commit *Commit) GetHeight() int64 { 800 return commit.Height 801 } 802 803 // GetRound returns height of the commit. 804 // Implements VoteSetReader. 805 func (commit *Commit) GetRound() int32 { 806 return commit.Round 807 } 808 809 // Size returns the number of signatures in the commit. 810 // Implements VoteSetReader. 811 func (commit *Commit) Size() int { 812 if commit == nil { 813 return 0 814 } 815 return len(commit.Signatures) 816 } 817 818 // BitArray returns a BitArray of which validators voted for BlockID or nil in this commit. 819 // Implements VoteSetReader. 820 func (commit *Commit) BitArray() *bits.BitArray { 821 if commit.bitArray == nil { 822 commit.bitArray = bits.NewBitArray(len(commit.Signatures)) 823 for i, commitSig := range commit.Signatures { 824 // TODO: need to check the BlockID otherwise we could be counting conflicts, 825 // not just the one with +2/3 ! 826 commit.bitArray.SetIndex(i, !commitSig.Absent()) 827 } 828 } 829 return commit.bitArray 830 } 831 832 // GetByIndex returns the vote corresponding to a given validator index. 833 // Panics if `index >= commit.Size()`. 834 // Implements VoteSetReader. 835 func (commit *Commit) GetByIndex(valIdx int32) *Vote { 836 return commit.GetVote(valIdx) 837 } 838 839 // IsCommit returns true if there is at least one signature. 840 // Implements VoteSetReader. 841 func (commit *Commit) IsCommit() bool { 842 return len(commit.Signatures) != 0 843 } 844 845 // ValidateBasic performs basic validation that doesn't involve state data. 846 // Does not actually check the cryptographic signatures. 847 func (commit *Commit) ValidateBasic() error { 848 if commit.Height < 0 { 849 return errors.New("negative Height") 850 } 851 if commit.Round < 0 { 852 return errors.New("negative Round") 853 } 854 855 if commit.Height >= 1 { 856 if commit.BlockID.IsZero() { 857 return errors.New("commit cannot be for nil block") 858 } 859 860 if len(commit.Signatures) == 0 { 861 return errors.New("no signatures in commit") 862 } 863 for i, commitSig := range commit.Signatures { 864 if err := commitSig.ValidateBasic(); err != nil { 865 return fmt.Errorf("wrong CommitSig #%d: %v", i, err) 866 } 867 } 868 } 869 return nil 870 } 871 872 // Hash returns the hash of the commit 873 func (commit *Commit) Hash() tmbytes.HexBytes { 874 if commit == nil { 875 return nil 876 } 877 if commit.hash == nil { 878 bs := make([][]byte, len(commit.Signatures)) 879 for i, commitSig := range commit.Signatures { 880 pbcs := commitSig.ToProto() 881 bz, err := pbcs.Marshal() 882 if err != nil { 883 panic(err) 884 } 885 886 bs[i] = bz 887 } 888 commit.hash = merkle.HashFromByteSlices(bs) 889 } 890 return commit.hash 891 } 892 893 // StringIndented returns a string representation of the commit 894 func (commit *Commit) StringIndented(indent string) string { 895 if commit == nil { 896 return "nil-Commit" 897 } 898 commitSigStrings := make([]string, len(commit.Signatures)) 899 for i, commitSig := range commit.Signatures { 900 commitSigStrings[i] = commitSig.String() 901 } 902 return fmt.Sprintf(`Commit{ 903 %s Height: %d 904 %s Round: %d 905 %s BlockID: %v 906 %s Signatures: 907 %s %v 908 %s}#%v`, 909 indent, commit.Height, 910 indent, commit.Round, 911 indent, commit.BlockID, 912 indent, 913 indent, strings.Join(commitSigStrings, "\n"+indent+" "), 914 indent, commit.hash) 915 } 916 917 // ToProto converts Commit to protobuf 918 func (commit *Commit) ToProto() *tmproto.Commit { 919 if commit == nil { 920 return nil 921 } 922 923 c := new(tmproto.Commit) 924 sigs := make([]tmproto.CommitSig, len(commit.Signatures)) 925 for i := range commit.Signatures { 926 sigs[i] = *commit.Signatures[i].ToProto() 927 } 928 c.Signatures = sigs 929 930 c.Height = commit.Height 931 c.Round = commit.Round 932 c.BlockID = commit.BlockID.ToProto() 933 if commit.hash != nil { 934 c.Hash = commit.hash 935 } 936 c.BitArray = commit.bitArray.ToProto() 937 return c 938 } 939 940 // FromProto sets a protobuf Commit to the given pointer. 941 // It returns an error if the commit is invalid. 942 func CommitFromProto(cp *tmproto.Commit) (*Commit, error) { 943 if cp == nil { 944 return nil, errors.New("nil Commit") 945 } 946 947 var ( 948 commit = new(Commit) 949 bitArray *bits.BitArray 950 ) 951 952 bi, err := BlockIDFromProto(&cp.BlockID) 953 if err != nil { 954 return nil, err 955 } 956 957 bitArray.FromProto(cp.BitArray) 958 959 sigs := make([]CommitSig, len(cp.Signatures)) 960 for i := range cp.Signatures { 961 if err := sigs[i].FromProto(cp.Signatures[i]); err != nil { 962 return nil, err 963 } 964 } 965 commit.Signatures = sigs 966 967 commit.Height = cp.Height 968 commit.Round = cp.Round 969 commit.BlockID = *bi 970 commit.hash = cp.Hash 971 commit.bitArray = bitArray 972 973 return commit, commit.ValidateBasic() 974 } 975 976 //----------------------------------------------------------------------------- 977 978 // SignedHeader is a header along with the commits that prove it. 979 // It is the basis of the light client. 980 type SignedHeader struct { 981 *Header `json:"header"` 982 983 Commit *Commit `json:"commit"` 984 } 985 986 // ValidateBasic does basic consistency checks and makes sure the header 987 // and commit are consistent. 988 // 989 // NOTE: This does not actually check the cryptographic signatures. Make sure 990 // to use a Verifier to validate the signatures actually provide a 991 // significantly strong proof for this header's validity. 992 func (sh SignedHeader) ValidateBasic(chainID string) error { 993 if sh.Header == nil { 994 return errors.New("missing header") 995 } 996 if sh.Commit == nil { 997 return errors.New("missing commit") 998 } 999 1000 if err := sh.Header.ValidateBasic(); err != nil { 1001 return fmt.Errorf("invalid header: %w", err) 1002 } 1003 if err := sh.Commit.ValidateBasic(); err != nil { 1004 return fmt.Errorf("invalid commit: %w", err) 1005 } 1006 1007 if sh.ChainID != chainID { 1008 return fmt.Errorf("header belongs to another chain %q, not %q", sh.ChainID, chainID) 1009 } 1010 1011 // Make sure the header is consistent with the commit. 1012 if sh.Commit.Height != sh.Height { 1013 return fmt.Errorf("header and commit height mismatch: %d vs %d", sh.Height, sh.Commit.Height) 1014 } 1015 if hhash, chash := sh.Hash(), sh.Commit.BlockID.Hash; !bytes.Equal(hhash, chash) { 1016 return fmt.Errorf("commit signs block %X, header is block %X", chash, hhash) 1017 } 1018 1019 return nil 1020 } 1021 1022 func (sh SignedHeader) String() string { 1023 return sh.StringIndented("") 1024 } 1025 1026 // StringIndented returns a string representation of the SignedHeader. 1027 func (sh SignedHeader) StringIndented(indent string) string { 1028 return fmt.Sprintf(`SignedHeader{ 1029 %s %v 1030 %s %v 1031 %s}`, 1032 indent, sh.Header.StringIndented(indent+" "), 1033 indent, sh.Commit.StringIndented(indent+" "), 1034 indent) 1035 } 1036 1037 // ToProto converts SignedHeader to protobuf 1038 func (sh *SignedHeader) ToProto() *tmproto.SignedHeader { 1039 if sh == nil { 1040 return nil 1041 } 1042 1043 psh := new(tmproto.SignedHeader) 1044 if sh.Header != nil { 1045 psh.Header = sh.Header.ToProto() 1046 } 1047 if sh.Commit != nil { 1048 psh.Commit = sh.Commit.ToProto() 1049 } 1050 1051 return psh 1052 } 1053 1054 // FromProto sets a protobuf SignedHeader to the given pointer. 1055 // It returns an error if the hader or the commit is invalid. 1056 func SignedHeaderFromProto(shp *tmproto.SignedHeader) (*SignedHeader, error) { 1057 if shp == nil { 1058 return nil, errors.New("nil SignedHeader") 1059 } 1060 1061 sh := new(SignedHeader) 1062 1063 if shp.Header != nil { 1064 h, err := HeaderFromProto(shp.Header) 1065 if err != nil { 1066 return nil, err 1067 } 1068 sh.Header = &h 1069 } 1070 1071 if shp.Commit != nil { 1072 c, err := CommitFromProto(shp.Commit) 1073 if err != nil { 1074 return nil, err 1075 } 1076 sh.Commit = c 1077 } 1078 1079 return sh, nil 1080 } 1081 1082 //----------------------------------------------------------------------------- 1083 1084 // Data contains the set of transactions included in the block 1085 type Data struct { 1086 1087 // Txs that will be applied by state @ block.Height+1. 1088 // NOTE: not all txs here are valid. We're just agreeing on the order first. 1089 // This means that block.AppHash does not include these txs. 1090 Txs Txs `json:"txs"` 1091 1092 // Volatile 1093 hash tmbytes.HexBytes 1094 } 1095 1096 // Hash returns the hash of the data 1097 func (data *Data) Hash() tmbytes.HexBytes { 1098 if data == nil { 1099 return (Txs{}).Hash() 1100 } 1101 if data.hash == nil { 1102 data.hash = data.Txs.Hash() // NOTE: leaves of merkle tree are TxIDs 1103 } 1104 return data.hash 1105 } 1106 1107 // StringIndented returns a string representation of the transactions 1108 func (data *Data) StringIndented(indent string) string { 1109 if data == nil { 1110 return "nil-Data" 1111 } 1112 txStrings := make([]string, tmmath.MinInt(len(data.Txs), 21)) 1113 for i, tx := range data.Txs { 1114 if i == 20 { 1115 txStrings[i] = fmt.Sprintf("... (%v total)", len(data.Txs)) 1116 break 1117 } 1118 txStrings[i] = fmt.Sprintf("%X (%d bytes)", tx.Hash(), len(tx)) 1119 } 1120 return fmt.Sprintf(`Data{ 1121 %s %v 1122 %s}#%v`, 1123 indent, strings.Join(txStrings, "\n"+indent+" "), 1124 indent, data.hash) 1125 } 1126 1127 // ToProto converts Data to protobuf 1128 func (data *Data) ToProto() tmproto.Data { 1129 tp := new(tmproto.Data) 1130 1131 if len(data.Txs) > 0 { 1132 txBzs := make([][]byte, len(data.Txs)) 1133 for i := range data.Txs { 1134 txBzs[i] = data.Txs[i] 1135 } 1136 tp.Txs = txBzs 1137 } 1138 1139 if data.hash != nil { 1140 tp.Hash = data.hash 1141 } 1142 1143 return *tp 1144 } 1145 1146 // DataFromProto takes a protobuf representation of Data & 1147 // returns the native type. 1148 func DataFromProto(dp *tmproto.Data) (Data, error) { 1149 if dp == nil { 1150 return Data{}, errors.New("nil data") 1151 } 1152 data := new(Data) 1153 1154 if len(dp.Txs) > 0 { 1155 txBzs := make(Txs, len(dp.Txs)) 1156 for i := range dp.Txs { 1157 txBzs[i] = Tx(dp.Txs[i]) 1158 } 1159 data.Txs = txBzs 1160 } else { 1161 data.Txs = Txs{} 1162 } 1163 1164 data.hash = dp.Hash 1165 1166 return *data, nil 1167 } 1168 1169 //----------------------------------------------------------------------------- 1170 1171 // EvidenceData contains any evidence of malicious wrong-doing by validators 1172 type EvidenceData struct { 1173 Evidence EvidenceList `json:"evidence"` 1174 1175 // Volatile 1176 hash tmbytes.HexBytes 1177 } 1178 1179 // Hash returns the hash of the data. 1180 func (data *EvidenceData) Hash() tmbytes.HexBytes { 1181 if data.hash == nil { 1182 data.hash = data.Evidence.Hash() 1183 } 1184 return data.hash 1185 } 1186 1187 // StringIndented returns a string representation of the evidence. 1188 func (data *EvidenceData) StringIndented(indent string) string { 1189 if data == nil { 1190 return "nil-Evidence" 1191 } 1192 evStrings := make([]string, tmmath.MinInt(len(data.Evidence), 21)) 1193 for i, ev := range data.Evidence { 1194 if i == 20 { 1195 evStrings[i] = fmt.Sprintf("... (%v total)", len(data.Evidence)) 1196 break 1197 } 1198 evStrings[i] = fmt.Sprintf("Evidence:%v", ev) 1199 } 1200 return fmt.Sprintf(`EvidenceData{ 1201 %s %v 1202 %s}#%v`, 1203 indent, strings.Join(evStrings, "\n"+indent+" "), 1204 indent, data.hash) 1205 } 1206 1207 // ToProto converts EvidenceData to protobuf 1208 func (data *EvidenceData) ToProto() (*tmproto.EvidenceData, error) { 1209 if data == nil { 1210 return nil, errors.New("nil evidence data") 1211 } 1212 1213 evi := new(tmproto.EvidenceData) 1214 eviBzs := make([]tmproto.Evidence, len(data.Evidence)) 1215 for i := range data.Evidence { 1216 protoEvi, err := EvidenceToProto(data.Evidence[i]) 1217 if err != nil { 1218 return nil, err 1219 } 1220 eviBzs[i] = *protoEvi 1221 } 1222 evi.Evidence = eviBzs 1223 1224 if data.hash != nil { 1225 evi.Hash = data.hash 1226 } 1227 1228 return evi, nil 1229 } 1230 1231 // FromProto sets a protobuf EvidenceData to the given pointer. 1232 func (data *EvidenceData) FromProto(eviData *tmproto.EvidenceData) error { 1233 if eviData == nil { 1234 return errors.New("nil evidenceData") 1235 } 1236 1237 eviBzs := make(EvidenceList, len(eviData.Evidence)) 1238 for i := range eviData.Evidence { 1239 evi, err := EvidenceFromProto(&eviData.Evidence[i]) 1240 if err != nil { 1241 return err 1242 } 1243 eviBzs[i] = evi 1244 } 1245 data.Evidence = eviBzs 1246 1247 data.hash = eviData.GetHash() 1248 1249 return nil 1250 } 1251 1252 //-------------------------------------------------------------------------------- 1253 1254 // BlockID 1255 type BlockID struct { 1256 Hash tmbytes.HexBytes `json:"hash"` 1257 PartSetHeader PartSetHeader `json:"parts"` 1258 } 1259 1260 // Equals returns true if the BlockID matches the given BlockID 1261 func (blockID BlockID) Equals(other BlockID) bool { 1262 return bytes.Equal(blockID.Hash, other.Hash) && 1263 blockID.PartSetHeader.Equals(other.PartSetHeader) 1264 } 1265 1266 // Key returns a machine-readable string representation of the BlockID 1267 func (blockID BlockID) Key() string { 1268 pbph := blockID.PartSetHeader.ToProto() 1269 bz, err := pbph.Marshal() 1270 if err != nil { 1271 panic(err) 1272 } 1273 1274 return string(blockID.Hash) + string(bz) 1275 } 1276 1277 // ValidateBasic performs basic validation. 1278 func (blockID BlockID) ValidateBasic() error { 1279 // Hash can be empty in case of POLBlockID in Proposal. 1280 if err := ValidateHash(blockID.Hash); err != nil { 1281 return fmt.Errorf("wrong Hash") 1282 } 1283 if err := blockID.PartSetHeader.ValidateBasic(); err != nil { 1284 return fmt.Errorf("wrong PartSetHeader: %v", err) 1285 } 1286 return nil 1287 } 1288 1289 // IsZero returns true if this is the BlockID of a nil block. 1290 func (blockID BlockID) IsZero() bool { 1291 return len(blockID.Hash) == 0 && 1292 blockID.PartSetHeader.IsZero() 1293 } 1294 1295 // IsComplete returns true if this is a valid BlockID of a non-nil block. 1296 func (blockID BlockID) IsComplete() bool { 1297 return len(blockID.Hash) == tmhash.Size && 1298 blockID.PartSetHeader.Total > 0 && 1299 len(blockID.PartSetHeader.Hash) == tmhash.Size 1300 } 1301 1302 // String returns a human readable string representation of the BlockID 1303 func (blockID BlockID) String() string { 1304 return fmt.Sprintf(`%v:%v`, blockID.Hash, blockID.PartSetHeader) 1305 } 1306 1307 // ToProto converts BlockID to protobuf 1308 func (blockID *BlockID) ToProto() tmproto.BlockID { 1309 if blockID == nil { 1310 return tmproto.BlockID{} 1311 } 1312 1313 return tmproto.BlockID{ 1314 Hash: blockID.Hash, 1315 PartSetHeader: blockID.PartSetHeader.ToProto(), 1316 } 1317 } 1318 1319 // FromProto sets a protobuf BlockID to the given pointer. 1320 // It returns an error if the block id is invalid. 1321 func BlockIDFromProto(bID *tmproto.BlockID) (*BlockID, error) { 1322 if bID == nil { 1323 return nil, errors.New("nil BlockID") 1324 } 1325 1326 blockID := new(BlockID) 1327 ph, err := PartSetHeaderFromProto(&bID.PartSetHeader) 1328 if err != nil { 1329 return nil, err 1330 } 1331 1332 blockID.PartSetHeader = *ph 1333 blockID.Hash = bID.Hash 1334 1335 return blockID, blockID.ValidateBasic() 1336 }