package dgn import ( "encoding/binary" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" "golang.org/x/crypto/sha3" "math/big" "sync/atomic" "time" ) type BHeader struct { ParentHash common.Hash `json:"parentHash" gencodec:"required"` UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` Coinbase common.Address `json:"miner" gencodec:"required"` Root common.Hash `json:"stateRoot" gencodec:"required"` TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` Bloom types.Bloom `json:"logsBloom" gencodec:"required"` Difficulty *big.Int `json:"difficulty" gencodec:"required"` Number *big.Int `json:"number" gencodec:"required"` GasLimit uint64 `json:"gasLimit" gencodec:"required"` GasUsed uint64 `json:"gasUsed" gencodec:"required"` Time uint64 `json:"timestamp" gencodec:"required"` Extra []byte `json:"extraData" gencodec:"required"` Election []byte `json:"election" gencodec:"required"` MixDigest common.Hash `json:"mixHash"` Nonce types.BlockNonce `json:"nonce"` // Signature values V *big.Int `json:"v" gencodec:"required"` R *big.Int `json:"r" gencodec:"required"` S *big.Int `json:"s" gencodec:"required"` } // Hash returns the block hash of the header, which is simply the keccak256 hash of its // RLP encoding. func (h *BHeader) Hash() common.Hash { return rlpHash(h) } func rlpHash(x interface{}) (h common.Hash) { hw := sha3.NewLegacyKeccak256() rlp.Encode(hw, x) hw.Sum(h[:0]) return h } // Block represents an entire block in the Ethereum blockchain. type Block struct { header *BHeader uncles []*BHeader transactions types.Transactions // caches hash atomic.Value size atomic.Value // Td is used by package core to store the total difficulty // of the chain up to and including the block. td *big.Int // These fields are used by package eth to track // inter-peer block relay. ReceivedAt time.Time ReceivedFrom interface{} } func (b *Block) Uncles() []*BHeader { return b.uncles } func (b *Block) Transactions() types.Transactions { return b.transactions } func (b *Block) Transaction(hash common.Hash) *types.Transaction { for _, transaction := range b.transactions { if transaction.Hash() == hash { return transaction } } return nil } func (b *Block) Number() *big.Int { return new(big.Int).Set(b.header.Number) } func (b *Block) GasLimit() uint64 { return b.header.GasLimit } func (b *Block) GasUsed() uint64 { return b.header.GasUsed } func (b *Block) Difficulty() *big.Int { return new(big.Int).Set(b.header.Difficulty) } func (b *Block) Time() uint64 { return b.header.Time } func (b *Block) NumberU64() uint64 { return b.header.Number.Uint64() } func (b *Block) MixDigest() common.Hash { return b.header.MixDigest } func (b *Block) Nonce() uint64 { return binary.BigEndian.Uint64(b.header.Nonce[:]) } func (b *Block) Bloom() types.Bloom { return b.header.Bloom } func (b *Block) Coinbase() common.Address { return b.header.Coinbase } func (b *Block) Root() common.Hash { return b.header.Root } func (b *Block) ParentHash() common.Hash { return b.header.ParentHash } func (b *Block) TxHash() common.Hash { return b.header.TxHash } func (b *Block) ReceiptHash() common.Hash { return b.header.ReceiptHash } func (b *Block) UncleHash() common.Hash { return b.header.UncleHash } func (b *Block) Extra() []byte { return common.CopyBytes(b.header.Extra) } // WithBody returns a new block with the given transaction and uncle contents. func (b *Block) WithBody(transactions []*types.Transaction, uncles []*BHeader) *Block { block := &Block{ header: CopyHeader(b.header), transactions: make([]*types.Transaction, len(transactions)), uncles: make([]*BHeader, len(uncles)), } copy(block.transactions, transactions) for i := range uncles { block.uncles[i] = CopyHeader(uncles[i]) } return block } // Hash returns the keccak256 hash of b's header. // The hash is computed on the first call and cached thereafter. func (b *Block) Hash() common.Hash { if hash := b.hash.Load(); hash != nil { return hash.(common.Hash) } v := b.header.Hash() b.hash.Store(v) return v } // CopyHeader creates a deep copy of a block header to prevent side effects from // modifying a header variable. func CopyHeader(h *BHeader) *BHeader { cpy := *h if cpy.Difficulty = new(big.Int); h.Difficulty != nil { cpy.Difficulty.Set(h.Difficulty) } if cpy.Number = new(big.Int); h.Number != nil { cpy.Number.Set(h.Number) } if len(h.Extra) > 0 { cpy.Extra = make([]byte, len(h.Extra)) copy(cpy.Extra, h.Extra) } return &cpy } func NewBlockWithHeader(header *BHeader) *Block { return &Block{header: CopyHeader(header)} }