github.com/amazechain/amc@v0.1.3/common/block/header.go (about)

     1  // Copyright 2022 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The AmazeChain library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package block
    18  
    19  import (
    20  	"encoding/binary"
    21  	"encoding/json"
    22  	"fmt"
    23  	"github.com/amazechain/amc/utils"
    24  	"github.com/holiman/uint256"
    25  	"google.golang.org/protobuf/proto"
    26  	"sync/atomic"
    27  
    28  	"github.com/amazechain/amc/api/protocol/types_pb"
    29  	"github.com/amazechain/amc/common/hexutil"
    30  	"github.com/amazechain/amc/common/types"
    31  )
    32  
    33  type BlockNonce [8]byte
    34  
    35  // EncodeNonce converts the given integer to a block nonce.
    36  func EncodeNonce(i uint64) BlockNonce {
    37  	var n BlockNonce
    38  	binary.BigEndian.PutUint64(n[:], i)
    39  	return n
    40  }
    41  
    42  // Uint64 returns the integer value of a block nonce.
    43  func (n BlockNonce) Uint64() uint64 {
    44  	return binary.BigEndian.Uint64(n[:])
    45  }
    46  
    47  // MarshalText todo copy eth
    48  func (n BlockNonce) MarshalText() ([]byte, error) {
    49  	return hexutil.Bytes(n[:]).MarshalText()
    50  }
    51  
    52  // UnmarshalText implements encoding.TextUnmarshaler.
    53  func (n *BlockNonce) UnmarshalText(input []byte) error {
    54  	return hexutil.UnmarshalFixedText("BlockNonce", input, n[:])
    55  }
    56  
    57  type Header struct {
    58  	ParentHash  types.Hash    `json:"parentHash"       gencodec:"required"`
    59  	Coinbase    types.Address `json:"miner"`
    60  	Root        types.Hash    `json:"stateRoot"        gencodec:"required"`
    61  	TxHash      types.Hash    `json:"transactionsRoot" gencodec:"required"`
    62  	ReceiptHash types.Hash    `json:"receiptsRoot"     gencodec:"required"`
    63  	Bloom       Bloom         `json:"logsBloom"        gencodec:"required"`
    64  	Difficulty  *uint256.Int  `json:"difficulty"       gencodec:"required"`
    65  	Number      *uint256.Int  `json:"number"           gencodec:"required"`
    66  	GasLimit    uint64        `json:"gasLimit"         gencodec:"required"`
    67  	GasUsed     uint64        `json:"gasUsed"          gencodec:"required"`
    68  	Time        uint64        `json:"timestamp"        gencodec:"required"`
    69  	MixDigest   types.Hash    `json:"mixHash"`
    70  	Nonce       BlockNonce    `json:"nonce"`
    71  	Extra       []byte        `json:"extraData"        gencodec:"required"`
    72  
    73  	// BaseFee was added by EIP-1559 and is ignored in legacy headers.
    74  	BaseFee *uint256.Int `json:"baseFeePerGas" rlp:"optional"`
    75  
    76  	hash atomic.Value
    77  
    78  	Signature types.Signature `json:"signature"`
    79  }
    80  
    81  func (h *Header) Number64() *uint256.Int {
    82  	return h.Number
    83  }
    84  
    85  func (h *Header) StateRoot() types.Hash {
    86  	return h.Root
    87  }
    88  
    89  func (h *Header) BaseFee64() *uint256.Int {
    90  	return h.BaseFee
    91  }
    92  
    93  func (h Header) Hash() types.Hash {
    94  	if hash := h.hash.Load(); hash != nil {
    95  		return hash.(types.Hash)
    96  	}
    97  
    98  	if h.BaseFee == nil {
    99  		h.BaseFee = uint256.NewInt(0)
   100  	}
   101  
   102  	if h.Difficulty == nil {
   103  		h.Difficulty = uint256.NewInt(0)
   104  	}
   105  
   106  	buf, err := json.Marshal(h)
   107  	if err != nil {
   108  		return types.Hash{}
   109  	}
   110  
   111  	if h.Number.Uint64() == 0 {
   112  		//log.Tracef("genesis header json Marshal: %s", string(buf))
   113  	}
   114  
   115  	hash := types.BytesHash(buf)
   116  	h.hash.Store(hash)
   117  	return hash
   118  }
   119  
   120  func (h *Header) ToProtoMessage() proto.Message {
   121  	return &types_pb.Header{
   122  		ParentHash:  utils.ConvertHashToH256(h.ParentHash),
   123  		Coinbase:    utils.ConvertAddressToH160(h.Coinbase),
   124  		Root:        utils.ConvertHashToH256(h.Root),
   125  		TxHash:      utils.ConvertHashToH256(h.TxHash),
   126  		ReceiptHash: utils.ConvertHashToH256(h.ReceiptHash),
   127  		Difficulty:  utils.ConvertUint256IntToH256(h.Difficulty),
   128  		Number:      utils.ConvertUint256IntToH256(h.Number),
   129  		GasLimit:    h.GasLimit,
   130  		GasUsed:     h.GasUsed,
   131  		Time:        h.Time,
   132  		Nonce:       h.Nonce.Uint64(),
   133  		BaseFee:     utils.ConvertUint256IntToH256(h.BaseFee),
   134  		Extra:       h.Extra,
   135  		Signature:   utils.ConvertSignatureToH768(h.Signature),
   136  		Bloom:       utils.ConvertBytesToH2048(h.Bloom.Bytes()),
   137  		MixDigest:   utils.ConvertHashToH256(h.MixDigest),
   138  	}
   139  }
   140  
   141  func (h *Header) FromProtoMessage(message proto.Message) error {
   142  	var (
   143  		pbHeader *types_pb.Header
   144  		ok       bool
   145  	)
   146  
   147  	if pbHeader, ok = message.(*types_pb.Header); !ok {
   148  		return fmt.Errorf("type conversion failure")
   149  	}
   150  
   151  	h.ParentHash = utils.ConvertH256ToHash(pbHeader.ParentHash)
   152  	h.Coinbase = utils.ConvertH160toAddress(pbHeader.Coinbase)
   153  	h.Root = utils.ConvertH256ToHash(pbHeader.Root)
   154  	h.TxHash = utils.ConvertH256ToHash(pbHeader.TxHash)
   155  	h.ReceiptHash = utils.ConvertH256ToHash(pbHeader.ReceiptHash)
   156  	h.Difficulty = utils.ConvertH256ToUint256Int(pbHeader.Difficulty)
   157  	h.Number = utils.ConvertH256ToUint256Int(pbHeader.Number)
   158  	h.GasLimit = pbHeader.GasLimit
   159  	h.GasUsed = pbHeader.GasUsed
   160  	h.Time = pbHeader.Time
   161  	h.Nonce = EncodeNonce(pbHeader.Nonce)
   162  	h.BaseFee = utils.ConvertH256ToUint256Int(pbHeader.BaseFee)
   163  	h.Extra = pbHeader.Extra
   164  	h.Signature = utils.ConvertH768ToSignature(pbHeader.Signature)
   165  	h.Bloom = utils.ConvertH2048ToBloom(pbHeader.Bloom)
   166  	h.MixDigest = utils.ConvertH256ToHash(pbHeader.MixDigest)
   167  	return nil
   168  }
   169  
   170  func (h *Header) Marshal() ([]byte, error) {
   171  	pbHeader := h.ToProtoMessage()
   172  	return proto.Marshal(pbHeader)
   173  }
   174  
   175  func (h *Header) Unmarshal(data []byte) error {
   176  	var pbHeader types_pb.Header
   177  	if err := proto.Unmarshal(data, &pbHeader); err != nil {
   178  		return err
   179  	}
   180  	if err := h.FromProtoMessage(&pbHeader); err != nil {
   181  		return err
   182  	}
   183  	return nil
   184  }
   185  
   186  func CopyHeader(h *Header) *Header {
   187  	cpy := *h
   188  
   189  	if cpy.Difficulty = uint256.NewInt(0); h.Difficulty != nil {
   190  		cpy.Difficulty.SetBytes(h.Difficulty.Bytes())
   191  	}
   192  	if cpy.Number = uint256.NewInt(0); h.Number != nil {
   193  		cpy.Number.SetBytes(h.Number.Bytes())
   194  	}
   195  
   196  	if h.BaseFee != nil {
   197  		cpy.BaseFee = uint256.NewInt(0).SetBytes(h.BaseFee.Bytes())
   198  	}
   199  
   200  	if len(h.Extra) > 0 {
   201  		cpy.Extra = make([]byte, len(h.Extra))
   202  		copy(cpy.Extra, h.Extra)
   203  	}
   204  	return &cpy
   205  }
   206  
   207  func CopyReward(rewards []*Reward) []*Reward {
   208  	var cpyReward []*Reward
   209  
   210  	for _, reward := range rewards {
   211  		addr, amount := types.Address{}, uint256.Int{}
   212  
   213  		addr.SetBytes(reward.Address[:])
   214  		cpyReward = append(cpyReward, &Reward{
   215  			Address: addr,
   216  			Amount:  amount.SetBytes(reward.Amount.Bytes()),
   217  		})
   218  	}
   219  
   220  	return cpyReward
   221  }