From 9e5257b83b8572077b9c26e4ae9a9443f765bf6e Mon Sep 17 00:00:00 2001
From: obscuren <geffobscura@gmail.com>
Date: Tue, 23 Dec 2014 14:33:15 +0100
Subject: [PATCH] Chain importer

---
 cmd/ethereum/flags.go     |  2 ++
 cmd/ethereum/main.go      | 28 +++++++++++++++++++++++++++-
 core/block_manager.go     |  4 ++--
 core/chain_manager.go     |  5 -----
 core/types/block.go       | 36 +++++++++++++++++++++---------------
 core/types/transaction.go | 28 ++++++++++++++--------------
 6 files changed, 66 insertions(+), 37 deletions(-)

diff --git a/cmd/ethereum/flags.go b/cmd/ethereum/flags.go
index 72f1db458..d27b739c3 100644
--- a/cmd/ethereum/flags.go
+++ b/cmd/ethereum/flags.go
@@ -58,6 +58,7 @@ var (
 	DumpHash        string
 	DumpNumber      int
 	VmType          int
+	ImportChain     string
 )
 
 // flags specific to cli client
@@ -104,6 +105,7 @@ func Init() {
 	flag.BoolVar(&DiffTool, "difftool", false, "creates output for diff'ing. Sets LogLevel=0")
 	flag.StringVar(&DiffType, "diff", "all", "sets the level of diff output [vm, all]. Has no effect if difftool=false")
 	flag.BoolVar(&ShowGenesis, "genesis", false, "Dump the genesis block")
+	flag.StringVar(&ImportChain, "chain", "", "Imports fiven chain")
 
 	flag.BoolVar(&Dump, "dump", false, "output the ethereum state in JSON format. Sub args [number, hash]")
 	flag.StringVar(&DumpHash, "hash", "", "specify arg in hex")
diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go
index fff9aedf8..f16244a2d 100644
--- a/cmd/ethereum/main.go
+++ b/cmd/ethereum/main.go
@@ -18,6 +18,7 @@
 package main
 
 import (
+	"bytes"
 	"fmt"
 	"os"
 	"runtime"
@@ -26,6 +27,7 @@ import (
 	"github.com/ethereum/go-ethereum/core/types"
 	"github.com/ethereum/go-ethereum/ethutil"
 	"github.com/ethereum/go-ethereum/logger"
+	"github.com/ethereum/go-ethereum/rlp"
 )
 
 const (
@@ -38,6 +40,10 @@ var clilogger = logger.NewLogger("CLI")
 func main() {
 	runtime.GOMAXPROCS(runtime.NumCPU())
 
+	defer func() {
+		logger.Flush()
+	}()
+
 	utils.HandleInterrupt()
 
 	// precedence: code-internal flag default < config file < environment variables < command line
@@ -112,6 +118,27 @@ func main() {
 		utils.StartMining(ethereum)
 	}
 
+	if len(ImportChain) > 0 {
+		clilogger.Infof("importing chain '%s'\n", ImportChain)
+		c, err := ethutil.ReadAllFile(ImportChain)
+		if err != nil {
+			clilogger.Infoln(err)
+			return
+		}
+		var chain types.Blocks
+		if err := rlp.Decode(bytes.NewReader([]byte(c)), &chain); err != nil {
+			clilogger.Infoln(err)
+			return
+		}
+
+		ethereum.ChainManager().Reset()
+		if err := ethereum.ChainManager().InsertChain(chain); err != nil {
+			clilogger.Infoln(err)
+			return
+		}
+		clilogger.Infof("imported %d blocks\n", len(chain))
+	}
+
 	// better reworked as cases
 	if StartJsConsole {
 		InitJsConsole(ethereum)
@@ -131,5 +158,4 @@ func main() {
 
 	// this blocks the thread
 	ethereum.WaitForShutdown()
-	logger.Flush()
 }
diff --git a/core/block_manager.go b/core/block_manager.go
index c61cf6504..ef2113bfb 100644
--- a/core/block_manager.go
+++ b/core/block_manager.go
@@ -304,7 +304,7 @@ func (sm *BlockManager) AccumelateRewards(statedb *state.StateDB, block, parent
 
 	knownUncles := set.New()
 	for _, uncle := range parent.Uncles() {
-		knownUncles.Add(uncle.Hash())
+		knownUncles.Add(string(uncle.Hash()))
 	}
 
 	nonces := ethutil.NewSet(block.Header().Nonce)
@@ -323,7 +323,7 @@ func (sm *BlockManager) AccumelateRewards(statedb *state.StateDB, block, parent
 			return UncleError("Uncle too old")
 		}
 
-		if knownUncles.Has(uncle.Hash()) {
+		if knownUncles.Has(string(uncle.Hash())) {
 			return UncleError("Uncle in chain")
 		}
 
diff --git a/core/chain_manager.go b/core/chain_manager.go
index e35c4aa3a..fe687e501 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -204,9 +204,6 @@ func (bc *ChainManager) Reset() {
 	bc.currentBlock = bc.genesisBlock
 
 	bc.setTotalDifficulty(ethutil.Big("0"))
-
-	// Set the last know difficulty (might be 0x0 as initial value, Genesis)
-	bc.td = ethutil.BigD(ethutil.Config.Db.LastKnownTD())
 }
 
 func (self *ChainManager) Export() []byte {
@@ -219,9 +216,7 @@ func (self *ChainManager) Export() []byte {
 	for block := self.currentBlock; block != nil; block = self.GetBlock(block.Header().ParentHash) {
 		blocks[block.NumberU64()] = block
 	}
-	//fmt.Println(blocks)
 
-	return nil
 	return ethutil.Encode(blocks)
 }
 
diff --git a/core/types/block.go b/core/types/block.go
index b0fcbdd9b..940f2402e 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -209,28 +209,34 @@ func (self *Block) HashNoNonce() []byte {
 
 func (self *Block) String() string {
 	return fmt.Sprintf(`BLOCK(%x): Size: %v {
+Header:
+[
 %v
+]
+Transactions:
 %v
+Uncles:
 %v
 }
-`, self.header.Hash(), self.Size(), self.header, self.uncles, self.transactions)
+`, self.header.Hash(), self.Size(), self.header, self.transactions, self.uncles)
 }
 
 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
+	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)
 }
 
diff --git a/core/types/transaction.go b/core/types/transaction.go
index c2f7df7a7..59244adc3 100644
--- a/core/types/transaction.go
+++ b/core/types/transaction.go
@@ -17,10 +17,10 @@ func IsContractAddr(addr []byte) bool {
 
 type Transaction struct {
 	AccountNonce uint64
+	Price        *big.Int
+	GasLimit     *big.Int
 	Recipient    []byte
 	Amount       *big.Int
-	GasAmount    *big.Int
-	Price        *big.Int
 	Payload      []byte
 	V            uint64
 	R, S         []byte
@@ -31,7 +31,7 @@ func NewContractCreationTx(Amount, gasAmount, price *big.Int, data []byte) *Tran
 }
 
 func NewTransactionMessage(to []byte, Amount, gasAmount, price *big.Int, data []byte) *Transaction {
-	return &Transaction{Recipient: to, Amount: Amount, Price: price, GasAmount: gasAmount, Payload: data}
+	return &Transaction{Recipient: to, Amount: Amount, Price: price, GasLimit: gasAmount, Payload: data}
 }
 
 func NewTransactionFromBytes(data []byte) *Transaction {
@@ -49,7 +49,7 @@ func NewTransactionFromAmount(val *ethutil.Value) *Transaction {
 }
 
 func (tx *Transaction) Hash() []byte {
-	data := []interface{}{tx.AccountNonce, tx.Price, tx.GasAmount, tx.Recipient, tx.Amount, tx.Payload}
+	data := []interface{}{tx.AccountNonce, tx.Price, tx.GasLimit, tx.Recipient, tx.Amount, tx.Payload}
 
 	return crypto.Sha3(ethutil.Encode(data))
 }
@@ -59,7 +59,7 @@ func (self *Transaction) Data() []byte {
 }
 
 func (self *Transaction) Gas() *big.Int {
-	return self.GasAmount
+	return self.GasLimit
 }
 
 func (self *Transaction) GasPrice() *big.Int {
@@ -140,7 +140,7 @@ func (tx *Transaction) Sign(privk []byte) error {
 }
 
 func (tx *Transaction) RlpData() interface{} {
-	data := []interface{}{tx.AccountNonce, tx.Price, tx.GasAmount, tx.Recipient, tx.Amount, tx.Payload}
+	data := []interface{}{tx.AccountNonce, tx.Price, tx.GasLimit, tx.Recipient, tx.Amount, tx.Payload}
 
 	return append(data, tx.V, new(big.Int).SetBytes(tx.R).Bytes(), new(big.Int).SetBytes(tx.S).Bytes())
 }
@@ -156,7 +156,7 @@ func (tx *Transaction) RlpDecode(data []byte) {
 func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) {
 	tx.AccountNonce = decoder.Get(0).Uint()
 	tx.Price = decoder.Get(1).BigInt()
-	tx.GasAmount = decoder.Get(2).BigInt()
+	tx.GasLimit = decoder.Get(2).BigInt()
 	tx.Recipient = decoder.Get(3).Bytes()
 	tx.Amount = decoder.Get(4).BigInt()
 	tx.Payload = decoder.Get(5).Bytes()
@@ -171,23 +171,23 @@ func (tx *Transaction) String() string {
 	Contract: %v
 	From:     %x
 	To:       %x
-	AccountNonce:    %v
-	GasAmountPrice: %v
-	GasAmount:      %v
-	Amount:    %v
+	Nonce:    %v
+	GasPrice: %v
+	GasLimit  %v
+	Value:    %v
 	Data:     0x%x
 	V:        0x%x
 	R:        0x%x
 	S:        0x%x
 	Hex:      %x
-	`,
+`,
 		tx.Hash(),
 		len(tx.Recipient) == 0,
 		tx.From(),
-		tx.Recipient,
+		tx.To(),
 		tx.AccountNonce,
 		tx.Price,
-		tx.GasAmount,
+		tx.GasLimit,
 		tx.Amount,
 		tx.Payload,
 		tx.V,