2014-11-18 07:58:22 -08:00
|
|
|
package types
|
2014-02-14 14:56:09 -08:00
|
|
|
|
|
|
|
import (
|
2014-05-22 08:56:33 -07:00
|
|
|
"bytes"
|
2014-02-14 14:56:09 -08:00
|
|
|
"fmt"
|
2014-07-26 02:24:44 -07:00
|
|
|
"math/big"
|
2014-09-15 06:42:12 -07:00
|
|
|
"sort"
|
2014-07-26 02:24:44 -07:00
|
|
|
"time"
|
|
|
|
|
2014-10-31 04:37:43 -07:00
|
|
|
"github.com/ethereum/go-ethereum/crypto"
|
2014-10-23 06:01:27 -07:00
|
|
|
"github.com/ethereum/go-ethereum/ethutil"
|
2014-12-23 04:48:44 -08:00
|
|
|
"github.com/ethereum/go-ethereum/rlp"
|
2014-02-14 14:56:09 -08:00
|
|
|
)
|
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
type Header struct {
|
2014-02-14 14:56:09 -08:00
|
|
|
// Hash to the previous block
|
2014-12-23 04:48:44 -08:00
|
|
|
ParentHash ethutil.Bytes
|
2014-02-14 14:56:09 -08:00
|
|
|
// Uncles of this block
|
2014-12-23 04:48:44 -08:00
|
|
|
UncleHash []byte
|
2014-02-14 14:56:09 -08:00
|
|
|
// The coin base address
|
|
|
|
Coinbase []byte
|
|
|
|
// Block Trie state
|
2014-12-23 04:48:44 -08:00
|
|
|
Root []byte
|
|
|
|
// Tx sha
|
|
|
|
TxHash []byte
|
|
|
|
// Receipt sha
|
|
|
|
ReceiptHash []byte
|
|
|
|
// Bloom
|
|
|
|
Bloom []byte
|
2014-02-14 14:56:09 -08:00
|
|
|
// Difficulty for the current block
|
|
|
|
Difficulty *big.Int
|
2014-05-20 05:29:52 -07:00
|
|
|
// The block number
|
|
|
|
Number *big.Int
|
|
|
|
// Gas limit
|
|
|
|
GasLimit *big.Int
|
|
|
|
// Gas used
|
|
|
|
GasUsed *big.Int
|
2014-12-23 04:48:44 -08:00
|
|
|
// Creation time
|
|
|
|
Time uint64
|
2014-02-14 14:56:09 -08:00
|
|
|
// Extra data
|
|
|
|
Extra string
|
|
|
|
// Block Nonce for verification
|
2014-09-15 06:42:12 -07:00
|
|
|
Nonce ethutil.Bytes
|
2014-02-14 14:56:09 -08:00
|
|
|
}
|
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
func (self *Header) rlpData(withNonce bool) []interface{} {
|
|
|
|
fields := []interface{}{self.ParentHash, self.UncleHash, self.Coinbase, self.Root, self.TxHash, self.ReceiptHash, self.Bloom, self.Difficulty, self.Number, self.GasLimit, self.GasUsed, self.Time, self.Extra}
|
|
|
|
if withNonce {
|
|
|
|
fields = append(fields, self.Nonce)
|
|
|
|
}
|
2014-02-14 14:56:09 -08:00
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
return fields
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *Header) RlpData() interface{} {
|
|
|
|
return self.rlpData(true)
|
2014-02-14 14:56:09 -08:00
|
|
|
}
|
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
func (self *Header) Hash() []byte {
|
|
|
|
return crypto.Sha3(ethutil.Encode(self.rlpData(true)))
|
|
|
|
}
|
2014-02-14 14:56:09 -08:00
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
func (self *Header) HashNoNonce() []byte {
|
|
|
|
return crypto.Sha3(ethutil.Encode(self.rlpData(false)))
|
2014-02-14 14:56:09 -08:00
|
|
|
}
|
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
type Block struct {
|
2015-01-05 08:10:42 -08:00
|
|
|
// Preset Hash for mock
|
|
|
|
HeaderHash []byte
|
|
|
|
ParentHeaderHash []byte
|
|
|
|
header *Header
|
|
|
|
uncles []*Header
|
|
|
|
transactions Transactions
|
|
|
|
Td *big.Int
|
2014-12-23 04:48:44 -08:00
|
|
|
|
|
|
|
receipts Receipts
|
|
|
|
Reward *big.Int
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewBlock(parentHash []byte, coinbase []byte, root []byte, difficulty *big.Int, nonce []byte, extra string) *Block {
|
|
|
|
header := &Header{
|
|
|
|
Root: root,
|
|
|
|
ParentHash: parentHash,
|
|
|
|
Coinbase: coinbase,
|
|
|
|
Difficulty: difficulty,
|
|
|
|
Nonce: nonce,
|
|
|
|
Time: uint64(time.Now().Unix()),
|
2014-11-28 11:47:24 -08:00
|
|
|
Extra: extra,
|
|
|
|
GasUsed: new(big.Int),
|
|
|
|
GasLimit: new(big.Int),
|
2014-02-14 14:56:09 -08:00
|
|
|
}
|
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
block := &Block{header: header, Reward: new(big.Int)}
|
2014-02-14 14:56:09 -08:00
|
|
|
|
|
|
|
return block
|
|
|
|
}
|
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
func NewBlockWithHeader(header *Header) *Block {
|
|
|
|
return &Block{header: header}
|
2014-02-14 14:56:09 -08:00
|
|
|
}
|
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
func (self *Block) DecodeRLP(s *rlp.Stream) error {
|
2015-01-05 08:10:42 -08:00
|
|
|
var extblock struct {
|
|
|
|
Header *Header
|
|
|
|
Txs []*Transaction
|
|
|
|
Uncles []*Header
|
|
|
|
TD *big.Int // optional
|
2014-02-14 14:56:09 -08:00
|
|
|
}
|
2015-01-05 08:10:42 -08:00
|
|
|
if err := s.Decode(&extblock); err != nil {
|
2014-12-23 04:48:44 -08:00
|
|
|
return err
|
|
|
|
}
|
2015-01-05 08:10:42 -08:00
|
|
|
self.header = extblock.Header
|
|
|
|
self.uncles = extblock.Uncles
|
|
|
|
self.transactions = extblock.Txs
|
|
|
|
self.Td = extblock.TD
|
2014-12-23 04:48:44 -08:00
|
|
|
return nil
|
2014-10-29 06:20:42 -07:00
|
|
|
}
|
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
func (self *Block) Header() *Header {
|
|
|
|
return self.header
|
2014-02-14 14:56:09 -08:00
|
|
|
}
|
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
func (self *Block) Uncles() []*Header {
|
|
|
|
return self.uncles
|
2014-02-14 14:56:09 -08:00
|
|
|
}
|
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
func (self *Block) SetUncles(uncleHeaders []*Header) {
|
|
|
|
self.uncles = uncleHeaders
|
|
|
|
self.header.UncleHash = crypto.Sha3(ethutil.Encode(uncleHeaders))
|
2014-02-14 14:56:09 -08:00
|
|
|
}
|
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
func (self *Block) Transactions() Transactions {
|
|
|
|
return self.transactions
|
2014-02-14 14:56:09 -08:00
|
|
|
}
|
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
func (self *Block) Transaction(hash []byte) *Transaction {
|
|
|
|
for _, transaction := range self.transactions {
|
|
|
|
if bytes.Equal(hash, transaction.Hash()) {
|
|
|
|
return transaction
|
2014-02-14 14:56:09 -08:00
|
|
|
}
|
|
|
|
}
|
2014-12-23 04:48:44 -08:00
|
|
|
return nil
|
2014-02-14 14:56:09 -08:00
|
|
|
}
|
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
func (self *Block) SetTransactions(transactions Transactions) {
|
|
|
|
self.transactions = transactions
|
|
|
|
self.header.TxHash = DeriveSha(transactions)
|
2014-10-29 02:34:40 -07:00
|
|
|
}
|
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
func (self *Block) Receipts() Receipts {
|
|
|
|
return self.receipts
|
2014-02-14 14:56:09 -08:00
|
|
|
}
|
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
func (self *Block) SetReceipts(receipts Receipts) {
|
|
|
|
self.receipts = receipts
|
|
|
|
self.header.ReceiptHash = DeriveSha(receipts)
|
|
|
|
self.header.Bloom = CreateBloom(receipts)
|
2014-10-10 13:42:37 -07:00
|
|
|
}
|
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
func (self *Block) RlpData() interface{} {
|
|
|
|
return []interface{}{self.header, self.transactions, self.uncles}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *Block) RlpDataForStorage() interface{} {
|
|
|
|
return []interface{}{self.header, self.transactions, self.uncles, self.Td /* TODO receipts */}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Header accessors (add as you need them)
|
2015-01-07 04:17:48 -08:00
|
|
|
func (self *Block) Number() *big.Int { return self.header.Number }
|
|
|
|
func (self *Block) NumberU64() uint64 { return self.header.Number.Uint64() }
|
|
|
|
func (self *Block) Bloom() []byte { return self.header.Bloom }
|
|
|
|
func (self *Block) Coinbase() []byte { return self.header.Coinbase }
|
|
|
|
func (self *Block) Time() int64 { return int64(self.header.Time) }
|
|
|
|
func (self *Block) GasLimit() *big.Int { return self.header.GasLimit }
|
|
|
|
func (self *Block) GasUsed() *big.Int { return self.header.GasUsed }
|
|
|
|
|
|
|
|
//func (self *Block) Trie() *ptrie.Trie { return ptrie.New(self.header.Root, ethutil.Config.Db) }
|
|
|
|
//func (self *Block) State() *state.StateDB { return state.New(self.Trie()) }
|
|
|
|
func (self *Block) Root() []byte { return self.header.Root }
|
2015-01-05 08:10:42 -08:00
|
|
|
func (self *Block) SetRoot(root []byte) { self.header.Root = root }
|
2014-12-23 04:48:44 -08:00
|
|
|
func (self *Block) Size() ethutil.StorageSize { return ethutil.StorageSize(len(ethutil.Encode(self))) }
|
|
|
|
|
2015-01-05 08:10:42 -08:00
|
|
|
// Implement pow.Block
|
2014-12-23 04:48:44 -08:00
|
|
|
func (self *Block) Difficulty() *big.Int { return self.header.Difficulty }
|
|
|
|
func (self *Block) N() []byte { return self.header.Nonce }
|
2015-01-05 08:10:42 -08:00
|
|
|
func (self *Block) HashNoNonce() []byte { return self.header.HashNoNonce() }
|
|
|
|
|
|
|
|
func (self *Block) Hash() []byte {
|
|
|
|
if self.HeaderHash != nil {
|
|
|
|
return self.HeaderHash
|
|
|
|
} else {
|
|
|
|
return self.header.Hash()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *Block) ParentHash() []byte {
|
|
|
|
if self.ParentHeaderHash != nil {
|
|
|
|
return self.ParentHeaderHash
|
|
|
|
} else {
|
|
|
|
return self.header.ParentHash
|
|
|
|
}
|
2014-12-23 04:48:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (self *Block) String() string {
|
2015-01-02 03:09:38 -08:00
|
|
|
return fmt.Sprintf(`BLOCK(%x): Size: %v TD: %v {
|
2014-12-23 05:33:15 -08:00
|
|
|
Header:
|
|
|
|
[
|
2014-12-23 04:48:44 -08:00
|
|
|
%v
|
2014-12-23 05:33:15 -08:00
|
|
|
]
|
|
|
|
Transactions:
|
2014-12-23 04:48:44 -08:00
|
|
|
%v
|
2014-12-23 05:33:15 -08:00
|
|
|
Uncles:
|
2014-12-23 04:48:44 -08:00
|
|
|
%v
|
|
|
|
}
|
2015-01-02 03:09:38 -08:00
|
|
|
`, self.header.Hash(), self.Size(), self.Td, self.header, self.transactions, self.uncles)
|
2014-12-23 04:48:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (self *Header) String() string {
|
2014-12-23 05:33:15 -08:00
|
|
|
return fmt.Sprintf(`
|
|
|
|
ParentHash: %x
|
|
|
|
UncleHash: %x
|
|
|
|
Coinbase: %x
|
|
|
|
Root: %x
|
|
|
|
TxSha %x
|
|
|
|
ReceiptSha: %x
|
|
|
|
Bloom: %x
|
|
|
|
Difficulty: %v
|
|
|
|
Number: %v
|
|
|
|
GasLimit: %v
|
|
|
|
GasUsed: %v
|
|
|
|
Time: %v
|
|
|
|
Extra: %v
|
|
|
|
Nonce: %x
|
2014-12-23 04:48:44 -08:00
|
|
|
`, self.ParentHash, self.UncleHash, self.Coinbase, self.Root, self.TxHash, self.ReceiptHash, self.Bloom, self.Difficulty, self.Number, self.GasLimit, self.GasUsed, self.Time, self.Extra, self.Nonce)
|
2014-03-20 03:20:29 -07:00
|
|
|
}
|
2014-02-14 14:56:09 -08:00
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
type Blocks []*Block
|
2014-10-10 13:42:37 -07:00
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
type BlockBy func(b1, b2 *Block) bool
|
2014-05-22 08:35:26 -07:00
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
func (self BlockBy) Sort(blocks Blocks) {
|
|
|
|
bs := blockSorter{
|
|
|
|
blocks: blocks,
|
|
|
|
by: self,
|
2014-02-14 14:56:09 -08:00
|
|
|
}
|
2014-12-23 04:48:44 -08:00
|
|
|
sort.Sort(bs)
|
2014-02-14 14:56:09 -08:00
|
|
|
}
|
2014-05-20 06:02:46 -07:00
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
type blockSorter struct {
|
|
|
|
blocks Blocks
|
|
|
|
by func(b1, b2 *Block) bool
|
2014-08-25 03:53:06 -07:00
|
|
|
}
|
2014-10-29 02:34:40 -07:00
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
func (self blockSorter) Len() int { return len(self.blocks) }
|
|
|
|
func (self blockSorter) Swap(i, j int) {
|
|
|
|
self.blocks[i], self.blocks[j] = self.blocks[j], self.blocks[i]
|
2014-10-29 02:34:40 -07:00
|
|
|
}
|
2014-12-23 04:48:44 -08:00
|
|
|
func (self blockSorter) Less(i, j int) bool { return self.by(self.blocks[i], self.blocks[j]) }
|
2014-12-10 07:45:16 -08:00
|
|
|
|
2014-12-23 04:48:44 -08:00
|
|
|
func Number(b1, b2 *Block) bool { return b1.Header().Number.Cmp(b2.Header().Number) < 0 }
|