Skip to content
Snippets Groups Projects
block.go 4.21 KiB
Newer Older
package bfa

import (
	"../util"
	"bytes"
	"encoding/hex"
	"errors"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/crypto/sha3"
	"github.com/ethereum/go-ethereum/rlp"
	"math/big"
	"strconv"
)

type BigInt big.Int

func (bigInt *BigInt) MarshalJSON() ([]byte, error) {
	return (*big.Int)(bigInt).MarshalJSON()
}

func (bigInt *BigInt) UnmarshalJSON(b []byte) error {
	if i, ok := new(big.Int).SetString(string(b[1:len(b)-1]), 0); ok {
		*bigInt = BigInt(*i)
		return nil
	}
	return errors.New("can't unmarshal BigInt")

}

func (bigInt *BigInt) String() string {
	return (*big.Int)(bigInt).String()
}

func (bigInt *BigInt) Int64() int64 {
	return (*big.Int)(bigInt).Int64()
}

func (bigInt *BigInt) Uint64() uint64 {
	return (*big.Int)(bigInt).Uint64()
}

func (bigInt *BigInt) IsZero() bool {
	return (*big.Int)(bigInt).BitLen() == 0
}

type Uint64 uint64

func (u *Uint64) UnmarshalJSON(b []byte) (err error) {
	i, err := strconv.ParseUint(string(b[1:len(b)-1]), 0, 64)
	*u = Uint64(i)
	return
}

type Bytes []byte

func (b Bytes) MarshalJSON() ([]byte, error) {
	dest := make([]byte, 2+hex.EncodedLen(len(b)))
	copy(dest, []byte("\"0x"))
	hex.Encode(dest[2:], b)
	dest[len(dest)-1] = '"'
	return dest, nil
}

func (b *Bytes) UnmarshalJSON(src []byte) (err error) {
	util.Require(len(src) >= 4 && bytes.Equal(src[1:3], []byte("0x")), "invalid json string")
	dest := make([]byte, hex.DecodedLen(len(src)-4))
	_, err = hex.Decode(dest, src[3:len(src)-1])
	if err == nil {
		*b = dest
	}
	return
}

// RPCTransaction represents a transaction
type RPCTransaction struct {
	BlockHash        common.Hash    `json:"blockHash"`
	BlockNumber      Uint64         `json:"blockNumber"`
	From             common.Address `json:"from"`
	Gas              Uint64         `json:"gas"`
	GasPrice         *BigInt        `json:"gasPrice"`
	Hash             common.Hash    `json:"hash"`
	Input            string         `json:"input"`
	Nonce            Uint64         `json:"nonce"`
	To               common.Address `json:"to"`
	TransactionIndex Uint64         `json:"transactionIndex"`
	Value            *BigInt        `json:"value"`
	V                *BigInt        `json:"v"`
	R                *BigInt        `json:"r"`
	S                *BigInt        `json:"s"`
}

type Header struct {
	ParentHash  common.Hash      `json:"parentHash"`
	UncleHash   common.Hash      `json:"sha3Uncles"`
	Coinbase    common.Address   `json:"miner"`
	Root        common.Hash      `json:"stateRoot"`
	TxHash      common.Hash      `json:"transactionsRoot"`
	ReceiptHash common.Hash      `json:"receiptsRoot"`
	Bloom       types.Bloom      `json:"logsBloom"`
	Difficulty  *BigInt          `json:"difficulty"`
	Number      *BigInt          `json:"number"`
	GasLimit    Uint64           `json:"gasLimit"`
	GasUsed     Uint64           `json:"gasUsed"`
	Time        *BigInt          `json:"timestamp"`
	Extra       Bytes            `json:"extraData"`
	MixDigest   common.Hash      `json:"mixHash"`
	Nonce       types.BlockNonce `json:"nonce"`
}

func (header *Header) ExtraWithoutSignature() []byte {
	return header.Extra[:len(header.Extra)-65]
}

func (header *Header) Signature() []byte {
	return header.Extra[len(header.Extra)-65:]
}

func (header *Header) ethHeader() *types.Header {
	var h types.Header
	h.ParentHash = header.ParentHash
	h.UncleHash = header.UncleHash
	h.Coinbase = header.Coinbase
	h.Root = header.Root
	h.TxHash = header.TxHash
	h.ReceiptHash = header.ReceiptHash
	h.Bloom = header.Bloom
	h.Difficulty = (*big.Int)(header.Difficulty)
	h.Number = (*big.Int)(header.Number)
	h.GasLimit = uint64(header.GasLimit)
	h.GasUsed = uint64(header.GasUsed)
	h.Time = (*big.Int)(header.Time)
	h.Extra = header.Extra
	h.MixDigest = header.MixDigest
	h.Nonce = header.Nonce
	return &h
}

func (header *Header) GetSigner() common.Address {
	return getSigner(header.ethHeader())
}

func (header *Header) GetHash() (h common.Hash) {
	hw := sha3.NewKeccak256()
	_ = rlp.Encode(hw, header.ethHeader())
	hw.Sum(h[:0])
	return h
}

type Block struct {
	Header
	Transactions    []RPCTransaction `json:"transactions"`
	TotalDifficulty Uint64           `json:"totalDifficulty"`
	Signer          common.Address   `json:"signer"`
	Hash            common.Hash      `json:"hash"`
}