Moved node to ethereum

This commit is contained in:
obscuren 2014-03-22 12:03:10 +01:00
parent 45ec9c88e4
commit 642630db15
3 changed files with 448 additions and 0 deletions

37
ethereum/config.go Normal file
View File

@ -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
ethereum/dev_console.go Normal file
View File

@ -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
ethereum/ethereum.go Normal file
View File

@ -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()
}