github.com/Gessiux/neatchain@v1.3.1/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/Gessiux/go-common" 11 "github.com/Gessiux/go-crypto" 12 "github.com/Gessiux/go-merkle" 13 "github.com/Gessiux/go-wire" 14 "github.com/Gessiux/neatchain/chain/core/state" 15 "github.com/Gessiux/neatchain/chain/core/types" 16 "github.com/Gessiux/neatchain/chain/log" 17 "github.com/Gessiux/neatchain/utilities/rlp" 18 ) 19 20 const MaxBlockSize = 22020096 // 21MB TODO make it configurable 21 22 // IntermediateBlockResult represents intermediate block execute result. 23 type IntermediateBlockResult struct { 24 Block *types.Block 25 // followed by block execute result 26 State *state.StateDB 27 Receipts types.Receipts 28 Ops *types.PendingOps 29 } 30 31 type NCBlock struct { 32 Block *types.Block `json:"block"` 33 NTCExtra *NeatConExtra `json:"ntcexdata"` 34 TX3ProofData []*types.TX3ProofData `json:"tx3proofdata"` 35 IntermediateResult *IntermediateBlockResult `json:"-"` 36 } 37 38 func MakeBlock(height uint64, chainID string, commit *Commit, 39 block *types.Block, valHash []byte, epochNumber uint64, epochBytes []byte, tx3ProofData []*types.TX3ProofData, partSize int) (*NCBlock, *PartSet) { 40 NTCExtra := &NeatConExtra{ 41 ChainID: chainID, 42 Height: uint64(height), 43 Time: time.Now(), 44 EpochNumber: epochNumber, 45 ValidatorsHash: valHash, 46 SeenCommit: commit, 47 EpochBytes: epochBytes, 48 } 49 50 ncBlock := &NCBlock{ 51 Block: block, 52 NTCExtra: NTCExtra, 53 TX3ProofData: tx3ProofData, 54 } 55 return ncBlock, ncBlock.MakePartSet(partSize) 56 } 57 58 // Basic validation that doesn't involve state data. 59 func (b *NCBlock) ValidateBasic(ncExtra *NeatConExtra) error { 60 61 if b.NTCExtra.ChainID != ncExtra.ChainID { 62 return errors.New(Fmt("Wrong Block.Header.ChainID. Expected %v, got %v", ncExtra.ChainID, b.NTCExtra.ChainID)) 63 } 64 if b.NTCExtra.Height != ncExtra.Height+1 { 65 return errors.New(Fmt("Wrong Block.Header.Height. Expected %v, got %v", ncExtra.Height+1, b.NTCExtra.Height)) 66 } 67 68 /* 69 if !b.NTCExtra.BlockID.Equals(blockID) { 70 return errors.New(Fmt("Wrong Block.Header.LastBlockID. Expected %v, got %v", blockID, b.NTCExtra.BlockID)) 71 } 72 if !bytes.Equal(b.NTCExtra.SeenCommitHash, b.NTCExtra.SeenCommit.Hash()) { 73 return errors.New(Fmt("Wrong Block.Header.LastCommitHash. Expected %X, got %X", b.NTCExtra.SeenCommitHash, b.NTCExtra.SeenCommit.Hash())) 74 } 75 if b.NTCExtra.Height != 1 { 76 if err := b.NTCExtra.SeenCommit.ValidateBasic(); err != nil { 77 return err 78 } 79 } 80 */ 81 return nil 82 } 83 84 func (b *NCBlock) FillSeenCommitHash() { 85 if b.NTCExtra.SeenCommitHash == nil { 86 b.NTCExtra.SeenCommitHash = b.NTCExtra.SeenCommit.Hash() 87 } 88 } 89 90 // Computes and returns the block hash. 91 // If the block is incomplete, block hash is nil for safety. 92 func (b *NCBlock) Hash() []byte { 93 // fmt.Println(">>", b.Data) 94 if b == nil || b.NTCExtra.SeenCommit == nil { 95 return nil 96 } 97 b.FillSeenCommitHash() 98 return b.NTCExtra.Hash() 99 } 100 101 func (b *NCBlock) MakePartSet(partSize int) *PartSet { 102 103 return NewPartSetFromData(b.ToBytes(), partSize) 104 } 105 106 func (b *NCBlock) ToBytes() []byte { 107 108 type TmpBlock struct { 109 BlockData []byte 110 NTCExtra *NeatConExtra 111 TX3ProofData []*types.TX3ProofData 112 } 113 //fmt.Printf("NCBlock.toBytes 0 with block: %v\n", b) 114 115 bs, err := rlp.EncodeToBytes(b.Block) 116 if err != nil { 117 log.Warnf("NCBlock.toBytes error\n") 118 } 119 bb := &TmpBlock{ 120 BlockData: bs, 121 NTCExtra: b.NTCExtra, 122 TX3ProofData: b.TX3ProofData, 123 } 124 125 ret := wire.BinaryBytes(bb) 126 return ret 127 } 128 129 func (b *NCBlock) FromBytes(reader io.Reader) (*NCBlock, error) { 130 131 type TmpBlock struct { 132 BlockData []byte 133 NTCExtra *NeatConExtra 134 TX3ProofData []*types.TX3ProofData 135 } 136 137 //fmt.Printf("NCBlock.FromBytes \n") 138 139 var n int 140 var err error 141 bb := wire.ReadBinary(&TmpBlock{}, reader, MaxBlockSize, &n, &err).(*TmpBlock) 142 if err != nil { 143 log.Warnf("NCBlock.FromBytes 0 error: %v\n", err) 144 return nil, err 145 } 146 147 var block types.Block 148 err = rlp.DecodeBytes(bb.BlockData, &block) 149 if err != nil { 150 log.Warnf("NCBlock.FromBytes 1 error: %v\n", err) 151 return nil, err 152 } 153 154 ncBlock := &NCBlock{ 155 Block: &block, 156 NTCExtra: bb.NTCExtra, 157 TX3ProofData: bb.TX3ProofData, 158 } 159 160 log.Debugf("NCBlock.FromBytes 2 with: %v\n", ncBlock) 161 return ncBlock, nil 162 } 163 164 // Convenience. 165 // A nil block never hashes to anything. 166 // Nothing hashes to a nil hash. 167 func (b *NCBlock) HashesTo(hash []byte) bool { 168 if len(hash) == 0 { 169 return false 170 } 171 if b == nil { 172 return false 173 } 174 return bytes.Equal(b.Hash(), hash) 175 } 176 177 func (b *NCBlock) String() string { 178 return b.StringIndented("") 179 } 180 181 func (b *NCBlock) StringIndented(indent string) string { 182 if b == nil { 183 return "nil-Block" 184 } 185 186 return fmt.Sprintf(`Block{ 187 %s %v 188 %s %v 189 %s %v 190 %s}#%X`, 191 indent, b.Block.String(), 192 indent, b.NTCExtra, 193 indent, b.NTCExtra.SeenCommit.StringIndented(indent+""), 194 indent, b.Hash()) 195 } 196 197 func (b *NCBlock) StringShort() string { 198 if b == nil { 199 return "nil-Block" 200 } else { 201 return fmt.Sprintf("Block#%X", b.Hash()) 202 } 203 } 204 205 //------------------------------------- 206 207 // NOTE: Commit is empty for height 1, but never nil. 208 type Commit struct { 209 // NOTE: The Precommits are in order of address to preserve the bonded ValidatorSet order. 210 // Any peer with a block can gossip precommits by index with a peer without recalculating the 211 // active ValidatorSet. 212 BlockID BlockID `json:"blockID"` 213 Height uint64 `json:"height"` 214 Round int `json:"round"` 215 216 // BLS signature aggregation to be added here 217 SignAggr crypto.BLSSignature `json:"SignAggr"` 218 BitArray *BitArray 219 220 // Volatile 221 hash []byte 222 } 223 224 func (commit *Commit) Type() byte { 225 return VoteTypePrecommit 226 } 227 228 func (commit *Commit) Size() int { 229 return (int)(commit.BitArray.Size()) 230 } 231 232 func (commit *Commit) NumCommits() int { 233 return (int)(commit.BitArray.NumBitsSet()) 234 } 235 236 func (commit *Commit) ValidateBasic() error { 237 if commit.BlockID.IsZero() { 238 return errors.New("Commit cannot be for nil block") 239 } 240 /* 241 if commit.Type() != VoteTypePrecommit { 242 return fmt.Errorf("Invalid commit type. Expected VoteTypePrecommit, got %v", 243 precommit.Type) 244 } 245 246 // shall we validate the signature aggregation? 247 */ 248 249 return nil 250 } 251 252 func (commit *Commit) Hash() []byte { 253 if commit.hash == nil { 254 hash := merkle.SimpleHashFromBinary(*commit) 255 commit.hash = hash 256 } 257 return commit.hash 258 } 259 260 func (commit *Commit) StringIndented(indent string) string { 261 if commit == nil { 262 return "nil-Commit" 263 } 264 return fmt.Sprintf(`Commit{ 265 %s BlockID: %v 266 %s Height: %v 267 %s Round: %v 268 %s Type: %v 269 %s BitArray: %v 270 %s}#%X`, 271 indent, commit.BlockID, 272 indent, commit.Height, 273 indent, commit.Round, 274 indent, commit.Type(), 275 indent, commit.BitArray.String(), 276 indent, commit.hash) 277 } 278 279 //-------------------------------------------------------------------------------- 280 281 type BlockID struct { 282 Hash []byte `json:"hash"` 283 PartsHeader PartSetHeader `json:"parts"` 284 } 285 286 func (blockID BlockID) IsZero() bool { 287 return len(blockID.Hash) == 0 && blockID.PartsHeader.IsZero() 288 } 289 290 func (blockID BlockID) Equals(other BlockID) bool { 291 return bytes.Equal(blockID.Hash, other.Hash) && 292 blockID.PartsHeader.Equals(other.PartsHeader) 293 } 294 295 func (blockID BlockID) Key() string { 296 return string(blockID.Hash) + string(wire.BinaryBytes(blockID.PartsHeader)) 297 } 298 299 func (blockID BlockID) WriteSignBytes(w io.Writer, n *int, err *error) { 300 if blockID.IsZero() { 301 wire.WriteTo([]byte("null"), w, n, err) 302 } else { 303 wire.WriteJSON(CanonicalBlockID(blockID), w, n, err) 304 } 305 306 } 307 308 func (blockID BlockID) String() string { 309 return fmt.Sprintf(`%X:%v`, blockID.Hash, blockID.PartsHeader) 310 }