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