Browse Source

Moved node to ethereum

obscuren 11 years ago
parent
commit
642630db15
3 changed files with 448 additions and 0 deletions
  1. 37 0
      ethereum/config.go
  2. 253 0
      ethereum/dev_console.go
  3. 158 0
      ethereum/ethereum.go

+ 37 - 0
ethereum/config.go

@@ -0,0 +1,37 @@
+package main
+
+import (
+	"flag"
+)
+
+var StartConsole bool
+var StartMining bool
+var UseUPnP bool
+var OutboundPort string
+var ShowGenesis bool
+var AddPeer string
+var MaxPeer int
+var GenAddr bool
+var UseSeed bool
+var ImportKey string
+var ExportKey bool
+
+//var UseGui bool
+var DataDir string
+
+func Init() {
+	flag.BoolVar(&StartConsole, "c", false, "debug and testing console")
+	flag.BoolVar(&StartMining, "m", false, "start dagger mining")
+	flag.BoolVar(&ShowGenesis, "g", false, "prints genesis header and exits")
+	//flag.BoolVar(&UseGui, "gui", true, "use the gui")
+	flag.BoolVar(&UseUPnP, "upnp", false, "enable UPnP support")
+	flag.BoolVar(&UseSeed, "seed", true, "seed peers")
+	flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
+	flag.BoolVar(&ExportKey, "export", false, "export private key")
+	flag.StringVar(&OutboundPort, "p", "30303", "listening port")
+	flag.StringVar(&DataDir, "dir", ".ethereum", "ethereum data directory")
+	flag.StringVar(&ImportKey, "import", "", "imports the given private key (hex)")
+	flag.IntVar(&MaxPeer, "x", 5, "maximum desired peers")
+
+	flag.Parse()
+}

+ 253 - 0
ethereum/dev_console.go

@@ -0,0 +1,253 @@
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/hex"
+	"errors"
+	"fmt"
+	"github.com/ethereum/eth-go"
+	"github.com/ethereum/eth-go/ethchain"
+	"github.com/ethereum/eth-go/ethdb"
+	"github.com/ethereum/eth-go/ethutil"
+	"github.com/ethereum/eth-go/ethwire"
+	_ "math/big"
+	"os"
+	"strings"
+)
+
+type Console struct {
+	db       *ethdb.MemDatabase
+	trie     *ethutil.Trie
+	ethereum *eth.Ethereum
+}
+
+func NewConsole(s *eth.Ethereum) *Console {
+	db, _ := ethdb.NewMemDatabase()
+	trie := ethutil.NewTrie(db, "")
+
+	return &Console{db: db, trie: trie, ethereum: s}
+}
+
+func (i *Console) ValidateInput(action string, argumentLength int) error {
+	err := false
+	var expArgCount int
+
+	switch {
+	case action == "update" && argumentLength != 2:
+		err = true
+		expArgCount = 2
+	case action == "get" && argumentLength != 1:
+		err = true
+		expArgCount = 1
+	case action == "dag" && argumentLength != 2:
+		err = true
+		expArgCount = 2
+	case action == "decode" && argumentLength != 1:
+		err = true
+		expArgCount = 1
+	case action == "encode" && argumentLength != 1:
+		err = true
+		expArgCount = 1
+	case action == "gettx" && argumentLength != 1:
+		err = true
+		expArgCount = 1
+	case action == "tx" && argumentLength != 2:
+		err = true
+		expArgCount = 2
+	case action == "getaddr" && argumentLength != 1:
+		err = true
+		expArgCount = 1
+	case action == "contract" && argumentLength != 1:
+		err = true
+		expArgCount = 1
+	case action == "say" && argumentLength != 1:
+		err = true
+		expArgCount = 1
+	case action == "addp" && argumentLength != 1:
+		err = true
+		expArgCount = 1
+	case action == "block" && argumentLength != 1:
+		err = true
+		expArgCount = 1
+	}
+
+	if err {
+		return errors.New(fmt.Sprintf("'%s' requires %d args, got %d", action, expArgCount, argumentLength))
+	} else {
+		return nil
+	}
+}
+
+func (i *Console) Editor() []string {
+	var buff bytes.Buffer
+	for {
+		reader := bufio.NewReader(os.Stdin)
+		str, _, err := reader.ReadLine()
+		if len(str) > 0 {
+			buff.Write(str)
+			buff.WriteString("\n")
+		}
+
+		if err != nil && err.Error() == "EOF" {
+			break
+		}
+	}
+
+	scanner := bufio.NewScanner(strings.NewReader(buff.String()))
+	scanner.Split(bufio.ScanLines)
+
+	var lines []string
+	for scanner.Scan() {
+		lines = append(lines, scanner.Text())
+	}
+
+	return lines
+}
+
+func (i *Console) PrintRoot() {
+	root := ethutil.NewValue(i.trie.Root)
+	if len(root.Bytes()) != 0 {
+		fmt.Println(hex.EncodeToString(root.Bytes()))
+	} else {
+		fmt.Println(i.trie.Root)
+	}
+}
+
+func (i *Console) ParseInput(input string) bool {
+	scanner := bufio.NewScanner(strings.NewReader(input))
+	scanner.Split(bufio.ScanWords)
+
+	count := 0
+	var tokens []string
+	for scanner.Scan() {
+		count++
+		tokens = append(tokens, scanner.Text())
+	}
+	if err := scanner.Err(); err != nil {
+		fmt.Fprintln(os.Stderr, "reading input:", err)
+	}
+
+	if len(tokens) == 0 {
+		return true
+	}
+
+	err := i.ValidateInput(tokens[0], count-1)
+	if err != nil {
+		fmt.Println(err)
+	} else {
+		switch tokens[0] {
+		case "update":
+			i.trie.Update(tokens[1], tokens[2])
+
+			i.PrintRoot()
+		case "get":
+			fmt.Println(i.trie.Get(tokens[1]))
+		case "root":
+			i.PrintRoot()
+		case "rawroot":
+			fmt.Println(i.trie.Root)
+		case "print":
+			i.db.Print()
+		case "dag":
+			fmt.Println(ethchain.DaggerVerify(ethutil.Big(tokens[1]), // hash
+				ethutil.BigPow(2, 36),   // diff
+				ethutil.Big(tokens[2]))) // nonce
+		case "decode":
+			value := ethutil.NewValueFromBytes([]byte(tokens[1]))
+			fmt.Println(value)
+		case "getaddr":
+			encoded, _ := hex.DecodeString(tokens[1])
+			addr := i.ethereum.BlockChain().CurrentBlock.State().GetAccount(encoded)
+			fmt.Println("addr:", addr)
+		case "block":
+			encoded, _ := hex.DecodeString(tokens[1])
+			block := i.ethereum.BlockChain().GetBlock(encoded)
+			info := block.BlockInfo()
+			fmt.Printf("++++++++++ #%d ++++++++++\n%v\n", info.Number, block)
+		case "say":
+			i.ethereum.Broadcast(ethwire.MsgTalkTy, []interface{}{tokens[1]})
+		case "addp":
+			i.ethereum.ConnectToPeer(tokens[1])
+		case "pcount":
+			fmt.Println("peers:", i.ethereum.Peers().Len())
+		case "encode":
+			fmt.Printf("%q\n", ethutil.Encode(tokens[1]))
+		case "tx":
+			recipient, err := hex.DecodeString(tokens[1])
+			if err != nil {
+				fmt.Println("recipient err:", err)
+			} else {
+				tx := ethchain.NewTransaction(recipient, ethutil.Big(tokens[2]), []string{""})
+
+				key := ethutil.Config.Db.GetKeys()[0]
+				tx.Sign(key.PrivateKey)
+				i.ethereum.TxPool().QueueTransaction(tx)
+
+				fmt.Printf("%x\n", tx.Hash())
+			}
+		case "gettx":
+			addr, _ := hex.DecodeString(tokens[1])
+			data, _ := ethutil.Config.Db.Get(addr)
+			if len(data) != 0 {
+				decoder := ethutil.NewValueFromBytes(data)
+				fmt.Println(decoder)
+			} else {
+				fmt.Println("gettx: tx not found")
+			}
+		case "contract":
+			fmt.Println("Contract editor (Ctrl-D = done)")
+			code := ethchain.Compile(i.Editor())
+
+			contract := ethchain.NewTransaction(ethchain.ContractAddr, ethutil.Big(tokens[1]), code)
+
+			key := ethutil.Config.Db.GetKeys()[0]
+			contract.Sign(key.PrivateKey)
+
+			i.ethereum.TxPool().QueueTransaction(contract)
+
+			fmt.Printf("%x\n", contract.Hash()[12:])
+		case "exit", "quit", "q":
+			return false
+		case "help":
+			fmt.Printf("COMMANDS:\n" +
+				"\033[1m= DB =\033[0m\n" +
+				"update KEY VALUE - Updates/Creates a new value for the given key\n" +
+				"get KEY - Retrieves the given key\n" +
+				"root - Prints the hex encoded merkle root\n" +
+				"rawroot - Prints the raw merkle root\n" +
+				"block HASH - Prints the block\n" +
+				"getaddr ADDR - Prints the account associated with the address\n" +
+				"\033[1m= Dagger =\033[0m\n" +
+				"dag HASH NONCE - Verifies a nonce with the given hash with dagger\n" +
+				"\033[1m= Encoding =\033[0m\n" +
+				"decode STR\n" +
+				"encode STR\n" +
+				"\033[1m= Other =\033[0m\n" +
+				"addp HOST:PORT\n" +
+				"tx TO AMOUNT\n" +
+				"contract AMOUNT\n")
+
+		default:
+			fmt.Println("Unknown command:", tokens[0])
+		}
+	}
+
+	return true
+}
+
+func (i *Console) Start() {
+	fmt.Printf("Eth Console. Type (help) for help\n")
+	reader := bufio.NewReader(os.Stdin)
+	for {
+		fmt.Printf("eth >>> ")
+		str, _, err := reader.ReadLine()
+		if err != nil {
+			fmt.Println("Error reading input", err)
+		} else {
+			if !i.ParseInput(string(str)) {
+				return
+			}
+		}
+	}
+}

+ 158 - 0
ethereum/ethereum.go

@@ -0,0 +1,158 @@
+package main
+
+import (
+	"fmt"
+	"github.com/ethereum/eth-go"
+	"github.com/ethereum/eth-go/ethchain"
+	"github.com/ethereum/eth-go/ethutil"
+	"github.com/ethereum/eth-go/ethwire"
+	"github.com/ethereum/go-ethereum/utils"
+	"log"
+	"os"
+	"os/signal"
+	"runtime"
+)
+
+const Debug = true
+
+// Register interrupt handlers so we can stop the ethereum
+func RegisterInterupts(s *eth.Ethereum) {
+	// Buffered chan of one is enough
+	c := make(chan os.Signal, 1)
+	// Notify about interrupts for now
+	signal.Notify(c, os.Interrupt)
+	go func() {
+		for sig := range c {
+			fmt.Printf("Shutting down (%v) ... \n", sig)
+
+			s.Stop()
+		}
+	}()
+}
+
+func main() {
+	Init()
+
+	runtime.GOMAXPROCS(runtime.NumCPU())
+
+	ethchain.InitFees()
+	ethutil.ReadConfig(DataDir)
+	ethutil.Config.Seed = UseSeed
+
+	// Instantiated a eth stack
+	ethereum, err := eth.New(eth.CapDefault, UseUPnP)
+	if err != nil {
+		log.Println("eth start err:", err)
+		return
+	}
+	ethereum.Port = OutboundPort
+
+	if GenAddr {
+		fmt.Println("This action overwrites your old private key. Are you sure? (y/n)")
+
+		var r string
+		fmt.Scanln(&r)
+		for ; ; fmt.Scanln(&r) {
+			if r == "n" || r == "y" {
+				break
+			} else {
+				fmt.Printf("Yes or no?", r)
+			}
+		}
+
+		if r == "y" {
+			utils.CreateKeyPair(true)
+		}
+		os.Exit(0)
+	} else {
+		if len(ImportKey) > 0 {
+			fmt.Println("This action overwrites your old private key. Are you sure? (y/n)")
+			var r string
+			fmt.Scanln(&r)
+			for ; ; fmt.Scanln(&r) {
+				if r == "n" || r == "y" {
+					break
+				} else {
+					fmt.Printf("Yes or no?", r)
+				}
+			}
+
+			if r == "y" {
+				utils.ImportPrivateKey(ImportKey)
+				os.Exit(0)
+			}
+		} else {
+			utils.CreateKeyPair(false)
+		}
+	}
+
+	if ExportKey {
+		key := ethutil.Config.Db.GetKeys()[0]
+		fmt.Printf("%x\n", key.PrivateKey)
+		os.Exit(0)
+	}
+
+	if ShowGenesis {
+		fmt.Println(ethereum.BlockChain().Genesis())
+		os.Exit(0)
+	}
+
+	log.Printf("Starting Ethereum v%s\n", ethutil.Config.Ver)
+
+	// Set the max peers
+	ethereum.MaxPeers = MaxPeer
+
+	if StartConsole {
+		err := os.Mkdir(ethutil.Config.ExecPath, os.ModePerm)
+		// Error is OK if the error is ErrExist
+		if err != nil && !os.IsExist(err) {
+			log.Panic("Unable to create EXECPATH:", err)
+		}
+
+		console := NewConsole(ethereum)
+		go console.Start()
+	}
+
+	RegisterInterupts(ethereum)
+	ethereum.Start()
+
+	if StartMining {
+		log.Printf("Miner started\n")
+
+		// Fake block mining. It broadcasts a new block every 5 seconds
+		go func() {
+			pow := &ethchain.EasyPow{}
+			data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
+			keyRing := ethutil.NewValueFromBytes(data)
+			addr := keyRing.Get(1).Bytes()
+
+			for {
+				txs := ethereum.TxPool().Flush()
+				// Create a new block which we're going to mine
+				block := ethereum.BlockChain().NewBlock(addr, txs)
+				log.Println("Mining on new block. Includes", len(block.Transactions()), "transactions")
+				// Apply all transactions to the block
+				ethereum.StateManager().ApplyTransactions(block, block.Transactions())
+
+				ethereum.StateManager().Prepare(block.State(), block.State())
+				ethereum.StateManager().AccumelateRewards(block)
+
+				// Search the nonce
+				block.Nonce = pow.Search(block)
+				ethereum.Broadcast(ethwire.MsgBlockTy, []interface{}{block.Value().Val})
+
+				ethereum.StateManager().PrepareDefault(block)
+				err := ethereum.StateManager().ProcessBlock(block)
+				if err != nil {
+					log.Println(err)
+				} else {
+					log.Println("\n+++++++ MINED BLK +++++++\n", ethereum.BlockChain().CurrentBlock)
+					log.Printf("🔨  Mined block %x\n", block.Hash())
+				}
+			}
+		}()
+	}
+
+	// Wait for shutdown
+	ethereum.WaitForShutdown()
+}