github.com/aergoio/aergo@v1.3.1/types/blockchain.go (about) 1 /** 2 * @file 3 * @copyright defined in aergo/LICENSE.txt 4 */ 5 6 package types 7 8 import ( 9 "bytes" 10 "encoding/binary" 11 "io" 12 "math" 13 "math/big" 14 "reflect" 15 "runtime" 16 "sync/atomic" 17 "time" 18 19 "github.com/aergoio/aergo/internal/enc" 20 "github.com/aergoio/aergo/internal/merkle" 21 "github.com/gogo/protobuf/proto" 22 "github.com/libp2p/go-libp2p-core/crypto" 23 "github.com/minio/sha256-simd" 24 ) 25 26 const ( 27 // DefaultMaxBlockSize is the maximum block size (currently 1MiB) 28 DefaultMaxBlockSize = 1 << 20 29 DefaultTxVerifyTime = time.Microsecond * 200 30 DefaultEvictPeriod = 12 31 32 // DefaultMaxHdrSize is the max size of the proto-buf serialized non-body 33 // fields. For the estimation detail, check 'TestBlockHeaderLimit' in 34 // 'blockchain_test.go.' Caution: Be sure to adjust the value below if the 35 // structure of the header is changed. 36 DefaultMaxHdrSize = 400 37 lastFieldOfBH = "Sign" 38 ) 39 40 type TxHash = []byte 41 type AvgTime struct { 42 val atomic.Value 43 mavg *MovingAverage 44 } 45 46 var ( 47 DefaultVerifierCnt = int(math.Max(float64(runtime.NumCPU()/2), float64(1))) 48 DefaultAvgTimeSize = 60 * 60 * 24 49 AvgTxVerifyTime *AvgTime = NewAvgTime(DefaultAvgTimeSize) 50 ) 51 52 //MaxAER is maximum value of aergo 53 var MaxAER *big.Int 54 55 //StakingMinimum is minimum amount for staking 56 var StakingMinimum *big.Int 57 58 ///NamePrice is default value of creating and updating name 59 var NamePrice *big.Int 60 61 var lastIndexOfBH int 62 63 func init() { 64 MaxAER, _ = new(big.Int).SetString("500000000000000000000000000", 10) 65 StakingMinimum, _ = new(big.Int).SetString("10000000000000000000000", 10) 66 NamePrice, _ = new(big.Int).SetString("1000000000000000000", 10) 67 lastIndexOfBH = getLastIndexOfBH() 68 } 69 70 // GetStakingMinimum returns the minimum limit of staking. 71 func GetStakingMinimum() *big.Int { 72 return StakingMinimum 73 } 74 75 func NewAvgTime(sizeMavg int) *AvgTime { 76 avgTime := &AvgTime{} 77 avgTime.mavg = NewMovingAverage(sizeMavg) 78 avgTime.val.Store(time.Duration(0)) 79 return avgTime 80 } 81 82 func (avgTime *AvgTime) Get() time.Duration { 83 var avg time.Duration 84 aopv := avgTime.val.Load() 85 if aopv != nil { 86 avg = aopv.(time.Duration) 87 } else { 88 panic("AvgTxSignTime is not set") 89 } 90 return avg 91 } 92 93 func (avgTime *AvgTime) UpdateAverage(cur time.Duration) time.Duration { 94 newAvg := time.Duration(avgTime.mavg.Add(int64(cur))) 95 avgTime.set(newAvg) 96 97 return newAvg 98 } 99 100 func (avgTime *AvgTime) set(val time.Duration) { 101 avgTime.val.Store(val) 102 } 103 104 func getLastIndexOfBH() (lastIndex int) { 105 v := reflect.ValueOf(BlockHeader{}) 106 107 nField := v.NumField() 108 var i int 109 for i = 0; i < nField; i++ { 110 name := v.Type().Field(i).Name 111 if name == lastFieldOfBH { 112 lastIndex = i 113 break 114 } 115 } 116 117 return i 118 } 119 120 type SystemValue int 121 122 const ( 123 StakingTotal SystemValue = 0 + iota 124 StakingMin 125 ) 126 127 func (s SystemValue) String() string { 128 return [...]string{"StakingTotal", "StakingMin"}[s] 129 } 130 131 // ChainAccessor is an interface for a another actor module to get info of chain 132 type ChainAccessor interface { 133 GetGenesisInfo() *Genesis 134 GetConsensusInfo() string 135 GetBestBlock() (*Block, error) 136 // GetBlock return block of blockHash. It return nil and error if not found block of that hash or there is a problem in db store 137 GetBlock(blockHash []byte) (*Block, error) 138 // GetHashByNo returns hash of block. It return nil and error if not found block of that number or there is a problem in db store 139 GetHashByNo(blockNo BlockNo) ([]byte, error) 140 GetChainStats() string 141 GetSystemValue(key SystemValue) (*big.Int, error) 142 143 // GetEnterpriseConfig always return non-nil object if there is no error, but it can return EnterpriseConfig with empty values 144 GetEnterpriseConfig(key string) (*EnterpriseConfig, error) 145 } 146 147 type SyncContext struct { 148 Seq uint64 149 150 PeerID PeerID 151 152 BestNo BlockNo 153 TargetNo BlockNo //sync target blockno 154 155 CommonAncestor *Block 156 157 TotalCnt uint64 158 RemainCnt uint64 159 LastAnchor BlockNo 160 161 NotifyC chan error 162 } 163 164 func NewSyncCtx(seq uint64, peerID PeerID, targetNo uint64, bestNo uint64, notifyC chan error) *SyncContext { 165 return &SyncContext{Seq: seq, PeerID: peerID, TargetNo: targetNo, BestNo: bestNo, LastAnchor: 0, NotifyC: notifyC} 166 } 167 168 func (ctx *SyncContext) SetAncestor(ancestor *Block) { 169 ctx.CommonAncestor = ancestor 170 ctx.TotalCnt = ctx.TargetNo - ctx.CommonAncestor.BlockNo() 171 ctx.RemainCnt = ctx.TotalCnt 172 } 173 174 // NodeInfo is used for actor message to send block info 175 type BlockInfo struct { 176 Hash []byte 177 No BlockNo 178 } 179 180 func (bi *BlockInfo) Equal(target *BlockInfo) bool { 181 if target == nil { 182 return false 183 } 184 185 if bi.No == target.No && bytes.Equal(bi.Hash, target.Hash) { 186 return true 187 } else { 188 return false 189 } 190 } 191 192 // BlockNo is the height of a block, which starts from 0 (genesis block). 193 type BlockNo = uint64 194 195 func Uint64ToBytes(num uint64) []byte { 196 buf := make([]byte, 8) 197 binary.LittleEndian.PutUint64(buf, num) 198 return buf 199 } 200 201 func BytesToUint64(data []byte) uint64 { 202 buf := binary.LittleEndian.Uint64(data) 203 return buf 204 } 205 206 // BlockNoToBytes represents to serialize block no to bytes 207 func BlockNoToBytes(bn BlockNo) []byte { 208 return Uint64ToBytes(bn) 209 } 210 211 // BlockNoFromBytes represents to deserialize bytes to block no 212 func BlockNoFromBytes(raw []byte) BlockNo { 213 buf := BytesToUint64(raw) 214 return BlockNo(buf) 215 } 216 217 // NewBlock represents to create a block to store transactions. 218 func NewBlock(prevBlock *Block, blockRoot []byte, receipts *Receipts, txs []*Tx, coinbaseAcc []byte, ts int64) *Block { 219 var ( 220 chainID []byte 221 prevBlockHash []byte 222 blockNo BlockNo 223 ) 224 225 if prevBlock != nil { 226 prevBlockHash = prevBlock.BlockHash() 227 blockNo = prevBlock.Header.BlockNo + 1 228 chainID = prevBlock.GetHeader().GetChainID() 229 } 230 231 body := BlockBody{ 232 Txs: txs, 233 } 234 header := BlockHeader{ 235 ChainID: chainID, 236 PrevBlockHash: prevBlockHash, 237 BlockNo: blockNo, 238 Timestamp: ts, 239 BlocksRootHash: blockRoot, 240 CoinbaseAccount: coinbaseAcc, 241 } 242 block := Block{ 243 Header: &header, 244 Body: &body, 245 } 246 247 block.Header.TxsRootHash = CalculateTxsRootHash(body.Txs) 248 block.Header.ReceiptsRootHash = receipts.MerkleRoot() 249 250 return &block 251 } 252 253 // Localtime retrurns a time.Time object, which is coverted from block 254 // timestamp. 255 func (block *Block) Localtime() time.Time { 256 return time.Unix(0, block.GetHeader().GetTimestamp()) 257 } 258 259 // calculateBlockHash computes sha256 hash of block header. 260 func (block *Block) calculateBlockHash() []byte { 261 digest := sha256.New() 262 serializeBH(digest, block.Header) 263 264 return digest.Sum(nil) 265 } 266 267 func serializeStruct(w io.Writer, s interface{}, stopIndex int) error { 268 v := reflect.Indirect(reflect.ValueOf(s)) 269 270 var i int 271 for i = 0; i <= stopIndex; i++ { 272 if err := binary.Write(w, binary.LittleEndian, v.Field(i).Interface()); err != nil { 273 return err 274 } 275 } 276 277 return nil 278 } 279 280 func serializeBH(w io.Writer, bh *BlockHeader) error { 281 return serializeStruct(w, bh, lastIndexOfBH) 282 } 283 284 func serializeBhForDigest(w io.Writer, bh *BlockHeader) error { 285 return serializeStruct(w, bh, lastIndexOfBH-1) 286 } 287 288 func writeBlockHeaderOld(w io.Writer, bh *BlockHeader) error { 289 for _, f := range []interface{}{ 290 bh.PrevBlockHash, 291 bh.BlockNo, 292 bh.Timestamp, 293 bh.BlocksRootHash, 294 bh.TxsRootHash, 295 bh.ReceiptsRootHash, 296 bh.Confirms, 297 bh.PubKey, 298 bh.Sign, 299 } { 300 if err := binary.Write(w, binary.LittleEndian, f); err != nil { 301 return err 302 } 303 } 304 305 return nil 306 } 307 308 // BlockHash returns block hash. It returns a calculated value if the hash is nil. 309 func (block *Block) BlockHash() []byte { 310 hash := block.GetHash() 311 if len(hash) == 0 { 312 block.Hash = block.calculateBlockHash() 313 } 314 315 return block.GetHash() 316 } 317 318 // BlockID converts block hash ([]byte) to BlockID. 319 func (block *Block) BlockID() BlockID { 320 return ToBlockID(block.BlockHash()) 321 } 322 323 // PrevBlockID converts parent block hash ([]byte) to BlockID. 324 func (block *Block) PrevBlockID() BlockID { 325 return ToBlockID(block.GetHeader().GetPrevBlockHash()) 326 } 327 328 // SetChainID sets id to block.ChainID 329 func (block *Block) SetChainID(id []byte) { 330 block.Header.ChainID = id 331 } 332 333 // ValidChildOf reports whether block is a varid child of parent. 334 func (block *Block) ValidChildOf(parent *Block) bool { 335 parChainID := parent.GetHeader().GetChainID() 336 curChainID := block.GetHeader().GetChainID() 337 338 // empty chain id case: an older verion of block has no chain id in its 339 // block header. 340 if len(parChainID) == 0 && len(curChainID) == 0 { 341 return true 342 } 343 344 return bytes.Compare(parChainID, curChainID) == 0 345 } 346 347 // Size returns a block size where the tx size is individually calculated. A 348 // similar method is used to limit the block size by the block factory. 349 // 350 // THE REASON WHY THE BLOCK FACTORY DOESN'T USE THE EXACT SIZE OF A MARSHALED 351 // BLOCK: The actual size of a marshaled block is larger than this because it 352 // includes an additional data associated with the marshaling of the 353 // transations array in the block body. It is ineffective that the (DPoS) block 354 // factory measures the exact size of the additional probuf data when it 355 // produces a block. Thus we use the slightly(?) different and less expensive 356 // estimation of the block size. 357 func (block *Block) Size() int { 358 size := proto.Size(block.GetHeader()) + len(block.GetHash()) 359 for _, tx := range block.GetBody().GetTxs() { 360 size += proto.Size(tx) 361 } 362 return size 363 } 364 365 // Confirms returns block.Header.Confirms which indicates how many block is confirmed 366 // by block. 367 func (block *Block) Confirms() BlockNo { 368 return block.GetHeader().GetConfirms() 369 } 370 371 // SetConfirms sets block.Header.Confirms to confirms. 372 func (block *Block) SetConfirms(confirms BlockNo) { 373 block.Header.Confirms = confirms 374 } 375 376 // BlockNo returns the block number of block. 377 func (block *Block) BlockNo() BlockNo { 378 return block.GetHeader().GetBlockNo() 379 } 380 381 // Sign adds a pubkey and a block signature to block. 382 func (block *Block) Sign(privKey crypto.PrivKey) error { 383 var err error 384 385 if err = block.setPubKey(privKey.GetPublic()); err != nil { 386 return err 387 } 388 389 var msg []byte 390 if msg, err = block.Header.bytesForDigest(); err != nil { 391 return err 392 } 393 394 var sig []byte 395 if sig, err = privKey.Sign(msg); err != nil { 396 return err 397 } 398 block.Header.Sign = sig 399 400 return nil 401 } 402 403 func (bh *BlockHeader) bytesForDigest() ([]byte, error) { 404 var buf bytes.Buffer 405 406 if err := serializeBhForDigest(&buf, bh); err != nil { 407 return nil, err 408 } 409 410 return buf.Bytes(), nil 411 } 412 413 // VerifySign verifies the signature of block. 414 func (block *Block) VerifySign() (valid bool, err error) { 415 var pubKey crypto.PubKey 416 if pubKey, err = crypto.UnmarshalPublicKey(block.Header.PubKey); err != nil { 417 return false, err 418 } 419 420 var msg []byte 421 if msg, err = block.Header.bytesForDigest(); err != nil { 422 return false, err 423 } 424 425 if valid, err = pubKey.Verify(msg, block.Header.Sign); err != nil { 426 return 427 } 428 429 return valid, nil 430 } 431 432 // BPID returns its Block Producer's ID from block. 433 func (block *Block) BPID() (id PeerID, err error) { 434 var pubKey crypto.PubKey 435 if pubKey, err = crypto.UnmarshalPublicKey(block.Header.PubKey); err != nil { 436 return PeerID(""), err 437 } 438 439 if id, err = IDFromPublicKey(pubKey); err != nil { 440 return PeerID(""), err 441 } 442 443 return 444 } 445 446 // BpID2Str returns its Block Producer's ID in base64 format. 447 func (block *Block) BPID2Str() string { 448 id, err := block.BPID() 449 if err != nil { 450 return "" 451 } 452 453 return enc.ToString([]byte(id)) 454 } 455 456 // ID returns the base64 encoded formated ID (hash) of block. 457 func (block *Block) ID() string { 458 hash := block.BlockHash() 459 if hash != nil { 460 return enc.ToString(hash) 461 } 462 463 return "" 464 465 } 466 467 // PrevID returns the base64 encoded formated ID (hash) of the parent block. 468 func (block *Block) PrevID() string { 469 hash := block.GetHeader().GetPrevBlockHash() 470 if hash != nil { 471 return enc.ToString(hash) 472 } 473 474 return "" 475 476 } 477 478 // SetPubKey sets block.Header.PubKey to pubkey. 479 func (block *Block) setPubKey(pubKey crypto.PubKey) error { 480 var pk []byte 481 var err error 482 if pk, err = pubKey.Bytes(); err != nil { 483 return err 484 } 485 block.Header.PubKey = pk 486 487 return nil 488 } 489 490 func (block *Block) SetBlocksRootHash(blockRootHash []byte) { 491 block.GetHeader().BlocksRootHash = blockRootHash 492 } 493 494 // GetMetadata generates Metadata object for block 495 func (block *Block) GetMetadata() *BlockMetadata { 496 return &BlockMetadata{ 497 Hash: block.BlockHash(), 498 Header: block.GetHeader(), 499 Txcount: int32(len(block.GetBody().GetTxs())), 500 Size: int64(proto.Size(block)), 501 } 502 } 503 504 // CalculateTxsRootHash generates merkle tree of transactions and returns root hash. 505 func CalculateTxsRootHash(txs []*Tx) []byte { 506 mes := make([]merkle.MerkleEntry, len(txs)) 507 for i, tx := range txs { 508 mes[i] = tx 509 } 510 return merkle.CalculateMerkleRoot(mes) 511 } 512 513 func NewTx() *Tx { 514 tx := &Tx{ 515 Body: &TxBody{ 516 Nonce: uint64(1), 517 }, 518 } 519 return tx 520 } 521 522 func (tx *Tx) CalculateTxHash() []byte { 523 txBody := tx.Body 524 digest := sha256.New() 525 binary.Write(digest, binary.LittleEndian, txBody.Nonce) 526 527 digest.Write(txBody.Account) 528 digest.Write(txBody.Recipient) 529 digest.Write(txBody.Amount) 530 digest.Write(txBody.Payload) 531 binary.Write(digest, binary.LittleEndian, txBody.GasLimit) 532 digest.Write(txBody.GasPrice) 533 binary.Write(digest, binary.LittleEndian, txBody.Type) 534 digest.Write(txBody.ChainIdHash) 535 digest.Write(txBody.Sign) 536 return digest.Sum(nil) 537 } 538 539 func (tx *Tx) NeedNameVerify() bool { 540 return tx.HasNameAccount() 541 } 542 543 func (tx *Tx) HasNameAccount() bool { 544 return len(tx.Body.Account) <= NameLength 545 } 546 547 func (tx *Tx) HasNameRecipient() bool { 548 return tx.Body.Recipient != nil && len(tx.Body.Recipient) <= NameLength 549 } 550 551 func (tx *Tx) Clone() *Tx { 552 if tx == nil { 553 return nil 554 } 555 if tx.Body == nil { 556 return &Tx{} 557 } 558 body := &TxBody{ 559 Nonce: tx.Body.Nonce, 560 Account: Clone(tx.Body.Account).([]byte), 561 Recipient: Clone(tx.Body.Recipient).([]byte), 562 Amount: Clone(tx.Body.Amount).([]byte), 563 Payload: Clone(tx.Body.Payload).([]byte), 564 GasLimit: tx.Body.GasLimit, 565 GasPrice: Clone(tx.Body.GasPrice).([]byte), 566 Type: tx.Body.Type, 567 ChainIdHash: Clone(tx.Body.ChainIdHash).([]byte), 568 Sign: Clone(tx.Body.Sign).([]byte), 569 } 570 res := &Tx{ 571 Body: body, 572 } 573 res.Hash = res.CalculateTxHash() 574 return res 575 } 576 577 func (b *TxBody) GetAmountBigInt() *big.Int { 578 return new(big.Int).SetBytes(b.GetAmount()) 579 } 580 581 func (b *TxBody) GetGasPriceBigInt() *big.Int { 582 return new(big.Int).SetBytes(b.GetGasPrice()) 583 } 584 585 type MovingAverage struct { 586 values []int64 587 size int 588 count int 589 590 sum int64 591 removedVal int64 592 curPos int 593 } 594 595 func NewMovingAverage(size int) *MovingAverage { 596 return &MovingAverage{ 597 values: make([]int64, size), 598 size: size, 599 removedVal: 0, 600 sum: 0, 601 curPos: -1, 602 count: 0, 603 } 604 } 605 606 func (ma *MovingAverage) Add(val int64) int64 { 607 ma.curPos = (ma.curPos + 1) % ma.size 608 ma.removedVal = ma.values[ma.curPos] 609 ma.values[ma.curPos] = val 610 611 if ma.count != ma.size { 612 ma.count++ 613 } 614 615 return ma.calculateAvg() 616 } 617 618 func (ma *MovingAverage) calculateAvg() int64 { 619 //values is empty 620 if ma.count == 0 { 621 return 0 622 } 623 624 ma.sum = ma.sum - ma.removedVal + ma.values[ma.curPos] 625 626 // Finalize average and return 627 avg := ma.sum / int64(ma.count) 628 return avg 629 }