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 }