github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/chain/consensus/neatcon/types/block.go (about)

     1  package types
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"io"
     8  	"time"
     9  
    10  	"github.com/neatlab/neatio/chain/core/state"
    11  	"github.com/neatlab/neatio/chain/core/types"
    12  	"github.com/neatlab/neatio/chain/log"
    13  	"github.com/neatlab/neatio/utilities/rlp"
    14  	. "github.com/neatlib/common-go"
    15  	"github.com/neatlib/crypto-go"
    16  	"github.com/neatlib/merkle-go"
    17  	"github.com/neatlib/wire-go"
    18  )
    19  
    20  const MaxBlockSize = 22020096
    21  
    22  type IntermediateBlockResult struct {
    23  	Block    *types.Block
    24  	State    *state.StateDB
    25  	Receipts types.Receipts
    26  	Ops      *types.PendingOps
    27  }
    28  
    29  type NCBlock struct {
    30  	Block              *types.Block             `json:"block"`
    31  	NTCExtra           *NeatConExtra            `json:"ntcexdata"`
    32  	TX3ProofData       []*types.TX3ProofData    `json:"tx3proofdata"`
    33  	IntermediateResult *IntermediateBlockResult `json:"-"`
    34  }
    35  
    36  func MakeBlock(height uint64, chainID string, commit *Commit,
    37  	block *types.Block, valHash []byte, epochNumber uint64, epochBytes []byte, tx3ProofData []*types.TX3ProofData, partSize int) (*NCBlock, *PartSet) {
    38  	NTCExtra := &NeatConExtra{
    39  		ChainID:        chainID,
    40  		Height:         uint64(height),
    41  		Time:           time.Now(),
    42  		EpochNumber:    epochNumber,
    43  		ValidatorsHash: valHash,
    44  		SeenCommit:     commit,
    45  		EpochBytes:     epochBytes,
    46  	}
    47  
    48  	ncBlock := &NCBlock{
    49  		Block:        block,
    50  		NTCExtra:     NTCExtra,
    51  		TX3ProofData: tx3ProofData,
    52  	}
    53  	return ncBlock, ncBlock.MakePartSet(partSize)
    54  }
    55  
    56  func (b *NCBlock) ValidateBasic(ncExtra *NeatConExtra) error {
    57  
    58  	if b.NTCExtra.ChainID != ncExtra.ChainID {
    59  		return errors.New(Fmt("Wrong Block.Header.ChainID. Expected %v, got %v", ncExtra.ChainID, b.NTCExtra.ChainID))
    60  	}
    61  	if b.NTCExtra.Height != ncExtra.Height+1 {
    62  		return errors.New(Fmt("Wrong Block.Header.Height. Expected %v, got %v", ncExtra.Height+1, b.NTCExtra.Height))
    63  	}
    64  
    65  	return nil
    66  }
    67  
    68  func (b *NCBlock) FillSeenCommitHash() {
    69  	if b.NTCExtra.SeenCommitHash == nil {
    70  		b.NTCExtra.SeenCommitHash = b.NTCExtra.SeenCommit.Hash()
    71  	}
    72  }
    73  
    74  func (b *NCBlock) Hash() []byte {
    75  	if b == nil || b.NTCExtra.SeenCommit == nil {
    76  		return nil
    77  	}
    78  	b.FillSeenCommitHash()
    79  	return b.NTCExtra.Hash()
    80  }
    81  
    82  func (b *NCBlock) MakePartSet(partSize int) *PartSet {
    83  
    84  	return NewPartSetFromData(b.ToBytes(), partSize)
    85  }
    86  
    87  func (b *NCBlock) ToBytes() []byte {
    88  
    89  	type TmpBlock struct {
    90  		BlockData    []byte
    91  		NTCExtra     *NeatConExtra
    92  		TX3ProofData []*types.TX3ProofData
    93  	}
    94  
    95  	bs, err := rlp.EncodeToBytes(b.Block)
    96  	if err != nil {
    97  		log.Warnf("NCBlock.toBytes error\n")
    98  	}
    99  	bb := &TmpBlock{
   100  		BlockData:    bs,
   101  		NTCExtra:     b.NTCExtra,
   102  		TX3ProofData: b.TX3ProofData,
   103  	}
   104  
   105  	ret := wire.BinaryBytes(bb)
   106  	return ret
   107  }
   108  
   109  func (b *NCBlock) FromBytes(reader io.Reader) (*NCBlock, error) {
   110  
   111  	type TmpBlock struct {
   112  		BlockData    []byte
   113  		NTCExtra     *NeatConExtra
   114  		TX3ProofData []*types.TX3ProofData
   115  	}
   116  
   117  	var n int
   118  	var err error
   119  	bb := wire.ReadBinary(&TmpBlock{}, reader, MaxBlockSize, &n, &err).(*TmpBlock)
   120  	if err != nil {
   121  		log.Warnf("NCBlock.FromBytes 0 error: %v\n", err)
   122  		return nil, err
   123  	}
   124  
   125  	var block types.Block
   126  	err = rlp.DecodeBytes(bb.BlockData, &block)
   127  	if err != nil {
   128  		log.Warnf("NCBlock.FromBytes 1 error: %v\n", err)
   129  		return nil, err
   130  	}
   131  
   132  	ncBlock := &NCBlock{
   133  		Block:        &block,
   134  		NTCExtra:     bb.NTCExtra,
   135  		TX3ProofData: bb.TX3ProofData,
   136  	}
   137  
   138  	log.Debugf("NCBlock.FromBytes 2 with: %v\n", ncBlock)
   139  	return ncBlock, nil
   140  }
   141  
   142  func (b *NCBlock) HashesTo(hash []byte) bool {
   143  	if len(hash) == 0 {
   144  		return false
   145  	}
   146  	if b == nil {
   147  		return false
   148  	}
   149  	return bytes.Equal(b.Hash(), hash)
   150  }
   151  
   152  func (b *NCBlock) String() string {
   153  	return b.StringIndented("")
   154  }
   155  
   156  func (b *NCBlock) StringIndented(indent string) string {
   157  	if b == nil {
   158  		return "nil-Block"
   159  	}
   160  
   161  	return fmt.Sprintf(`Block{
   162  %s  %v
   163  %s  %v
   164  %s  %v
   165  %s}#%X`,
   166  		indent, b.Block.String(),
   167  		indent, b.NTCExtra,
   168  		indent, b.NTCExtra.SeenCommit.StringIndented(indent+""),
   169  		indent, b.Hash())
   170  }
   171  
   172  func (b *NCBlock) StringShort() string {
   173  	if b == nil {
   174  		return "nil-Block"
   175  	} else {
   176  		return fmt.Sprintf("Block#%X", b.Hash())
   177  	}
   178  }
   179  
   180  type Commit struct {
   181  	BlockID BlockID `json:"blockID"`
   182  	Height  uint64  `json:"height"`
   183  	Round   int     `json:"round"`
   184  
   185  	SignAggr crypto.BLSSignature `json:"SignAggr"`
   186  	BitArray *BitArray
   187  
   188  	hash []byte
   189  }
   190  
   191  func (commit *Commit) Type() byte {
   192  	return VoteTypePrecommit
   193  }
   194  
   195  func (commit *Commit) Size() int {
   196  	return (int)(commit.BitArray.Size())
   197  }
   198  
   199  func (commit *Commit) NumCommits() int {
   200  	return (int)(commit.BitArray.NumBitsSet())
   201  }
   202  
   203  func (commit *Commit) ValidateBasic() error {
   204  	if commit.BlockID.IsZero() {
   205  		return errors.New("Commit cannot be for nil block")
   206  	}
   207  	return nil
   208  }
   209  
   210  func (commit *Commit) Hash() []byte {
   211  	if commit.hash == nil {
   212  		hash := merkle.SimpleHashFromBinary(*commit)
   213  		commit.hash = hash
   214  	}
   215  	return commit.hash
   216  }
   217  
   218  func (commit *Commit) StringIndented(indent string) string {
   219  	if commit == nil {
   220  		return "nil-Commit"
   221  	}
   222  	return fmt.Sprintf(`Commit{
   223  %s  BlockID:    %v
   224  %s  Height:     %v
   225  %s  Round:      %v
   226  %s  Type:       %v
   227  %s  BitArray:   %v
   228  %s}#%X`,
   229  		indent, commit.BlockID,
   230  		indent, commit.Height,
   231  		indent, commit.Round,
   232  		indent, commit.Type(),
   233  		indent, commit.BitArray.String(),
   234  		indent, commit.hash)
   235  }
   236  
   237  type BlockID struct {
   238  	Hash        []byte        `json:"hash"`
   239  	PartsHeader PartSetHeader `json:"parts"`
   240  }
   241  
   242  func (blockID BlockID) IsZero() bool {
   243  	return len(blockID.Hash) == 0 && blockID.PartsHeader.IsZero()
   244  }
   245  
   246  func (blockID BlockID) Equals(other BlockID) bool {
   247  	return bytes.Equal(blockID.Hash, other.Hash) &&
   248  		blockID.PartsHeader.Equals(other.PartsHeader)
   249  }
   250  
   251  func (blockID BlockID) Key() string {
   252  	return string(blockID.Hash) + string(wire.BinaryBytes(blockID.PartsHeader))
   253  }
   254  
   255  func (blockID BlockID) WriteSignBytes(w io.Writer, n *int, err *error) {
   256  	if blockID.IsZero() {
   257  		wire.WriteTo([]byte("null"), w, n, err)
   258  	} else {
   259  		wire.WriteJSON(CanonicalBlockID(blockID), w, n, err)
   260  	}
   261  
   262  }
   263  
   264  func (blockID BlockID) String() string {
   265  	return fmt.Sprintf(`%X:%v`, blockID.Hash, blockID.PartsHeader)
   266  }