@ -9,408 +9,252 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/trie"
)
type BlockInfo struct {
Number uint64
Hash [ ] byte
Parent [ ] byte
TD * big . Int
}
func ( bi * BlockInfo ) RlpDecode ( data [ ] byte ) {
decoder := ethutil . NewValueFromBytes ( data )
bi . Number = decoder . Get ( 0 ) . Uint ( )
bi . Hash = decoder . Get ( 1 ) . Bytes ( )
bi . Parent = decoder . Get ( 2 ) . Bytes ( )
bi . TD = decoder . Get ( 3 ) . BigInt ( )
}
func ( bi * BlockInfo ) RlpEncode ( ) [ ] byte {
return ethutil . Encode ( [ ] interface { } { bi . Number , bi . Hash , bi . Parent , bi . TD } )
}
type Blocks [ ] * Block
func ( self Blocks ) AsSet ( ) ethutil . UniqueSet {
set := make ( ethutil . UniqueSet )
for _ , block := range self {
set . Insert ( block . Hash ( ) )
}
return set
}
type BlockBy func ( b1 , b2 * Block ) bool
func ( self BlockBy ) Sort ( blocks Blocks ) {
bs := blockSorter {
blocks : blocks ,
by : self ,
}
sort . Sort ( bs )
}
type blockSorter struct {
blocks Blocks
by func ( b1 , b2 * Block ) bool
}
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 ]
}
func ( self blockSorter ) Less ( i , j int ) bool { return self . by ( self . blocks [ i ] , self . blocks [ j ] ) }
func Number ( b1 , b2 * Block ) bool { return b1 . Number . Cmp ( b2 . Number ) < 0 }
type Block struct {
type Header struct {
// Hash to the previous block
Prev Hash ethutil . Bytes
ParentHash ethutil . Bytes
// Uncles of this block
Uncles Blocks
UncleSha [ ] byte
UncleHash [ ] byte
// The coin base address
Coinbase [ ] byte
// Block Trie state
//state *ethutil.Trie
state * state . StateDB
Root [ ] byte
// Tx sha
TxHash [ ] byte
// Receipt sha
ReceiptHash [ ] byte
// Bloom
Bloom [ ] byte
// Difficulty for the current block
Difficulty * big . Int
// Creation time
Time int64
// The block number
Number * big . Int
// Gas limit
GasLimit * big . Int
// Gas used
GasUsed * big . Int
// Creation time
Time uint64
// Extra data
Extra string
// Block Nonce for verification
Nonce ethutil . Bytes
// List of transactions and/or contracts
transactions Transactions
receipts Receipts
TxSha , ReceiptSha [ ] byte
LogsBloom [ ] byte
Reward * big . Int
}
func NewBlockFromBytes ( raw [ ] byte ) * Block {
block := & Block { }
block . RlpDecode ( raw )
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 )
}
return block
return fields
}
func ( self * Header ) RlpData ( ) interface { } {
return self . rlpData ( true )
}
// New block takes a raw encoded string
func NewBlockFromRlpValue ( rlpValue * ethutil . Value ) * Block {
block := & Block { }
block . RlpValueDecode ( rlpValue )
func ( self * Header ) Hash ( ) [ ] byte {
return crypto . Sha3 ( ethutil . Encode ( self . rlpData ( true ) ) )
}
return block
func ( self * Header ) HashNoNonce ( ) [ ] byte {
return crypto . Sha3 ( ethutil . Encode ( self . rlpData ( false ) ) )
}
func CreateBlock ( root interface { } ,
prevHash [ ] byte ,
base [ ] byte ,
Difficulty * big . Int ,
Nonce [ ] byte ,
extra string ) * Block {
block := & Block {
PrevHash : prevHash ,
Coinbase : base ,
Difficulty : Difficulty ,
Nonce : Nonce ,
Time : time . Now ( ) . Unix ( ) ,
type Block struct {
header * Header
uncles [ ] * Header
transactions Transactions
Td * big . Int
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 ( ) ) ,
Extra : extra ,
UncleSha : nil ,
GasUsed : new ( big . Int ) ,
GasLimit : new ( big . Int ) ,
}
block . SetUncles ( [ ] * Block { } )
block . state = state . New ( trie . New ( ethutil . Config . Db , root ) )
block := & Block { header : header , Reward : new ( big . Int ) }
return block
}
// Returns a hash of the block
func ( block * Block ) Hash ( ) ethutil . Bytes {
return crypto . Sha3 ( ethutil . NewValue ( block . header ( ) ) . Encode ( ) )
//return crypto.Sha3(block.Value().Encode())
}
func ( block * Block ) HashNoNonce ( ) [ ] byte {
return crypto . Sha3 ( ethutil . Encode ( block . miningHeader ( ) ) )
}
func ( block * Block ) State ( ) * state . StateDB {
return block . state
}
func ( block * Block ) Transactions ( ) Transactions {
return block . transactions
func NewBlockWithHeader ( header * Header ) * Block {
return & Block { header : header }
}
func ( block * Block ) CalcGasLimit ( parent * Block ) * big . Int {
if block . Number . Cmp ( big . NewInt ( 0 ) ) == 0 {
return ethutil . BigPow ( 10 , 6 )
func ( self * Block ) DecodeRLP ( s * rlp . Stream ) error {
if _ , err := s . List ( ) ; err != nil {
return err
}
// ((1024-1) * parent.gasLimit + (gasUsed * 6 / 5)) / 1024
previous := new ( big . Int ) . Mul ( big . NewInt ( 1024 - 1 ) , parent . GasLimit )
current := new ( big . Rat ) . Mul ( new ( big . Rat ) . SetInt ( parent . GasUsed ) , big . NewRat ( 6 , 5 ) )
curInt := new ( big . Int ) . Div ( current . Num ( ) , current . Denom ( ) )
result := new ( big . Int ) . Add ( previous , curInt )
result . Div ( result , big . NewInt ( 1024 ) )
min := big . NewInt ( 125000 )
return ethutil . BigMax ( min , result )
}
func ( block * Block ) BlockInfo ( ) BlockInfo {
bi := BlockInfo { }
data , _ := ethutil . Config . Db . Get ( append ( block . Hash ( ) , [ ] byte ( "Info" ) ... ) )
bi . RlpDecode ( data )
return bi
}
func ( self * Block ) GetTransaction ( hash [ ] byte ) * Transaction {
for _ , tx := range self . transactions {
if bytes . Compare ( tx . Hash ( ) , hash ) == 0 {
return tx
}
var header Header
if err := s . Decode ( & header ) ; err != nil {
return err
}
return nil
}
// Sync the block's state and contract respectively
func ( block * Block ) Sync ( ) {
block . state . Sync ( )
}
func ( block * Block ) Undo ( ) {
// Sync the block state itself
block . state . Reset ( )
}
/////// Block Encoding
func ( block * Block ) rlpReceipts ( ) interface { } {
// Marshal the transactions of this block
encR := make ( [ ] interface { } , len ( block . receipts ) )
for i , r := range block . receipts {
// Cast it to a string (safe)
encR [ i ] = r . RlpData ( )
var transactions [ ] * Transaction
if err := s . Decode ( & transactions ) ; err != nil {
return err
}
return encR
}
var uncleHeaders [ ] * Header
if err := s . Decode ( & uncleHeaders ) ; err != nil {
return err
}
func ( block * Block ) rlpUncles ( ) interface { } {
// Marshal the transactions of this block
uncles := make ( [ ] interface { } , len ( block . Uncles ) )
for i , uncle := range block . Uncles {
// Cast it to a string (safe)
uncles [ i ] = uncle . header ( )
var tdBytes [ ] byte
if err := s . Decode ( & tdBytes ) ; err != nil {
// If this block comes from the network that's fine. If loaded from disk it should be there
// Blocks don't store their Td when propagated over the network
} else {
self . Td = ethutil . BigD ( tdBytes )
}
return uncles
}
if err := s . ListEnd ( ) ; err != nil {
return err
}
func ( block * Block ) SetUncles ( uncles [ ] * Block ) {
block . Uncles = uncles
block . UncleSha = crypto . Sha3 ( ethutil . Encode ( block . rlpUncles ( ) ) )
}
self . header = & header
self . uncles = uncleHeaders
self . transactions = transactions
func ( self * Block ) SetReceipts ( receipts Receipts ) {
self . receipts = receipts
self . ReceiptSha = DeriveSha ( receipts )
self . LogsBloom = CreateBloom ( receipts )
return nil
}
func ( self * Block ) SetTransactions ( txs Transactions ) {
self . transactions = txs
self . TxSha = DeriveSha ( txs )
func ( self * Block ) Header ( ) * Header {
return self . header
}
func ( block * Block ) Value ( ) * ethutil . Value {
return ethutil . NewValue ( [ ] interface { } { block . header ( ) , block . transactions , block . rlpUncles ( ) } )
func ( self * Block ) Uncles ( ) [ ] * Header {
return self . uncles
}
func ( block * Block ) RlpEncode ( ) [ ] byte {
// Encode a slice interface which contains the header and the list of
// transactions.
return block . Value ( ) . Encode ( )
func ( self * Block ) SetUncles ( uncleHeaders [ ] * Header ) {
self . uncles = uncleHeaders
self . header . UncleHash = crypto . Sha3 ( ethutil . Encode ( uncleHeaders ) )
}
func ( block * Block ) RlpDecode ( data [ ] byte ) {
rlpValue := ethutil . NewValueFromBytes ( data )
block . RlpValueDecode ( rlpValue )
func ( self * Block ) Transactions ( ) Transactions {
return self . transactions
}
func ( block * Block ) RlpValueDecode ( decoder * ethutil . Value ) {
block . setHeader ( decoder . Get ( 0 ) )
// Tx list might be empty if this is an uncle. Uncles only have their
// header set.
if decoder . Get ( 1 ) . IsNil ( ) == false { // Yes explicitness
//receipts := decoder.Get(1)
//block.receipts = make([]*Receipt, receipts.Len())
txs := decoder . Get ( 1 )
block . transactions = make ( Transactions , txs . Len ( ) )
for i := 0 ; i < txs . Len ( ) ; i ++ {
block . transactions [ i ] = NewTransactionFromValue ( txs . Get ( i ) )
//receipt := NewRecieptFromValue(receipts.Get(i))
//block.transactions[i] = receipt.Tx
//block.receipts[i] = receipt
}
}
if decoder . Get ( 2 ) . IsNil ( ) == false { // Yes explicitness
uncles := decoder . Get ( 2 )
block . Uncles = make ( [ ] * Block , uncles . Len ( ) )
for i := 0 ; i < uncles . Len ( ) ; i ++ {
block . Uncles [ i ] = NewUncleBlockFromValue ( uncles . Get ( i ) )
func ( self * Block ) Transaction ( hash [ ] byte ) * Transaction {
for _ , transaction := range self . transactions {
if bytes . Equal ( hash , transaction . Hash ( ) ) {
return transaction
}
}
return nil
}
func ( self * Block ) setHeader ( header * ethutil . Value ) {
self . PrevHash = header . Get ( 0 ) . Bytes ( )
self . UncleSha = header . Get ( 1 ) . Bytes ( )
self . Coinbase = header . Get ( 2 ) . Bytes ( )
self . state = state . New ( trie . New ( ethutil . Config . Db , header . Get ( 3 ) . Val ) )
self . TxSha = header . Get ( 4 ) . Bytes ( )
self . ReceiptSha = header . Get ( 5 ) . Bytes ( )
self . LogsBloom = header . Get ( 6 ) . Bytes ( )
self . Difficulty = header . Get ( 7 ) . BigInt ( )
self . Number = header . Get ( 8 ) . BigInt ( )
self . GasLimit = header . Get ( 9 ) . BigInt ( )
self . GasUsed = header . Get ( 10 ) . BigInt ( )
self . Time = int64 ( header . Get ( 11 ) . BigInt ( ) . Uint64 ( ) )
self . Extra = header . Get ( 12 ) . Str ( )
self . Nonce = header . Get ( 13 ) . Bytes ( )
func ( self * Block ) SetTransactions ( transactions Transactions ) {
self . transactions = transactions
self . header . TxHash = DeriveSha ( transactions )
}
func NewUncleBlockFromValue ( header * ethutil . Value ) * Block {
block := & Block { }
block . setHeader ( header )
return block
func ( self * Block ) Receipts ( ) Receipts {
return self . receipts
}
func ( block * Block ) Trie ( ) * trie . Trie {
return block . state . Trie
func ( self * Block ) SetReceipts ( receipts Receipts ) {
self . receipts = receipts
self . header . ReceiptHash = DeriveSha ( receipts )
self . header . Bloom = CreateBloom ( receipts )
}
func ( block * Block ) Root ( ) interface { } {
return block . state . Root ( )
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)
func ( self * Block ) Number ( ) * big . Int { return self . header . Number }
func ( self * Block ) NumberU64 ( ) uint64 { return self . header . Number . Uint64 ( ) }
func ( self * Block ) ParentHash ( ) [ ] byte { return self . header . ParentHash }
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 ) Hash ( ) [ ] byte { return self . header . Hash ( ) }
func ( self * Block ) Trie ( ) * trie . Trie { return trie . New ( ethutil . Config . Db , self . header . Root ) }
func ( self * Block ) State ( ) * state . StateDB { return state . New ( self . Trie ( ) ) }
func ( self * Block ) Size ( ) ethutil . StorageSize { return ethutil . StorageSize ( len ( ethutil . Encode ( self ) ) ) }
// Implement block.Pow
func ( self * Block ) Difficulty ( ) * big . Int { return self . header . Difficulty }
func ( self * Block ) N ( ) [ ] byte { return self . header . Nonce }
func ( self * Block ) HashNoNonce ( ) [ ] byte {
return crypto . Sha3 ( ethutil . Encode ( self . header . rlpData ( false ) ) )
}
func ( self * Block ) String ( ) string {
return fmt . Sprintf ( ` BLOCK ( % x ) : Size : % v {
% v
% v
% v
}
` , self . header . Hash ( ) , self . Size ( ) , self . header , self . uncles , self . transactions )
}
func ( self * Header ) String ( ) string {
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
` , 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 )
}
func ( block * Block ) Diff ( ) * big . Int {
return block . Difficulty
}
type Blocks [ ] * Block
func ( self * Block ) Receipts ( ) [ ] * Receipt {
return self . receipts
}
type BlockBy func ( b1 , b2 * Block ) bool
func ( block * Block ) miningHeader ( ) [ ] interface { } {
return [ ] interface { } {
// Sha of the previous block
block . PrevHash ,
// Sha of uncles
block . UncleSha ,
// Coinbase address
block . Coinbase ,
// root state
block . Root ( ) ,
// tx root
block . TxSha ,
// Sha of tx
block . ReceiptSha ,
// Bloom
block . LogsBloom ,
// Current block Difficulty
block . Difficulty ,
// The block number
block . Number ,
// Block upper gas bound
block . GasLimit ,
// Block gas used
block . GasUsed ,
// Time the block was found?
block . Time ,
// Extra data
block . Extra ,
func ( self BlockBy ) Sort ( blocks Blocks ) {
bs := blockSorter {
blocks : blocks ,
by : self ,
}
sort . Sort ( bs )
}
func ( block * Block ) header ( ) [ ] interface { } {
return append ( block . miningHeader ( ) , block . Nonce )
}
func ( block * Block ) String ( ) string {
return fmt . Sprintf ( `
BLOCK ( % x ) : Size : % v
PrevHash : % x
UncleSha : % x
Coinbase : % x
Root : % x
TxSha % x
ReceiptSha : % x
Bloom : % x
Difficulty : % v
Number : % v
MaxLimit : % v
GasUsed : % v
Time : % v
Extra : % v
Nonce : % x
NumTx : % v
` ,
block . Hash ( ) ,
block . Size ( ) ,
block . PrevHash ,
block . UncleSha ,
block . Coinbase ,
block . Root ( ) ,
block . TxSha ,
block . ReceiptSha ,
block . LogsBloom ,
block . Difficulty ,
block . Number ,
block . GasLimit ,
block . GasUsed ,
block . Time ,
block . Extra ,
block . Nonce ,
len ( block . transactions ) ,
)
}
func ( self * Block ) Size ( ) ethutil . StorageSize {
return ethutil . StorageSize ( len ( self . RlpEncode ( ) ) )
type blockSorter struct {
blocks Blocks
by func ( b1 , b2 * Block ) bool
}
// Implement RlpEncodable
func ( self * Block ) RlpData ( ) interface { } {
return [ ] interface { } { self . header ( ) , self . transactions , self . rlpUncles ( ) }
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 ]
}
func ( self blockSorter ) Less ( i , j int ) bool { return self . by ( self . blocks [ i ] , self . blocks [ j ] ) }
// Implement pow.Block
func ( self * Block ) N ( ) [ ] byte { return self . Nonce }
func Number ( b1 , b2 * Block ) bool { return b1 . Header ( ) . Number . Cmp ( b2 . Header ( ) . Number ) < 0 }