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