From 8bbf879cb31e9cb28700773ed788421f9935ac36 Mon Sep 17 00:00:00 2001 From: obscuren Date: Fri, 10 Jan 2014 22:44:53 +0100 Subject: Moving the ethgo to individual packages --- big.go | 35 --------- block.go | 192 ------------------------------------------------- block_manager.go | 17 ++--- bytes.go | 27 ------- contract.go | 65 ----------------- dagger.go | 7 +- database.go | 56 --------------- database_test.go | 7 -- dev_console.go | 20 +++--- encoding.go | 62 ---------------- encoding_test.go | 38 ---------- ethereum.go | 6 +- genesis.go | 34 --------- memory_database.go | 34 --------- parsing.go | 98 ------------------------- parsing_test.go | 33 --------- rlp.go | 3 +- server.go | 10 +-- transaction.go | 206 ----------------------------------------------------- trie.go | 203 ---------------------------------------------------- trie_test.go | 59 --------------- util.go | 63 ---------------- vm.go | 22 +++--- 23 files changed, 46 insertions(+), 1251 deletions(-) delete mode 100644 big.go delete mode 100644 block.go delete mode 100644 bytes.go delete mode 100644 contract.go delete mode 100644 database.go delete mode 100644 database_test.go delete mode 100644 encoding.go delete mode 100644 encoding_test.go delete mode 100644 genesis.go delete mode 100644 memory_database.go delete mode 100644 parsing.go delete mode 100644 parsing_test.go delete mode 100644 transaction.go delete mode 100644 trie.go delete mode 100644 trie_test.go delete mode 100644 util.go diff --git a/big.go b/big.go deleted file mode 100644 index b0fbcb64f..000000000 --- a/big.go +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - "math/big" -) - -/* - * Returns the power of two integers - */ -func BigPow(a,b int) *big.Int { - c := new(big.Int) - c.Exp(big.NewInt(int64(a)), big.NewInt(int64(b)), big.NewInt(0)) - - return c -} - -/* - * Like big.NewInt(uint64); this takes a string instead. - */ -func Big(num string) *big.Int { - n := new(big.Int) - n.SetString(num, 0) - - return n -} - -/* - * Like big.NewInt(uint64); this takes a byte buffer instead. - */ -func BigD(data []byte) *big.Int { - n := new(big.Int) - n.SetBytes(data) - - return n -} diff --git a/block.go b/block.go deleted file mode 100644 index 2287a9d55..000000000 --- a/block.go +++ /dev/null @@ -1,192 +0,0 @@ -package main - -import ( - "fmt" - "time" - _"bytes" - _"encoding/hex" -) - -type Block struct { - // The number of this block - number uint32 - // Hash to the previous block - prevHash string - // Uncles of this block - uncles []*Block - coinbase string - // state xxx - state *Trie - difficulty uint32 - // Creation time - time int64 - nonce uint32 - // List of transactions and/or contracts - transactions []*Transaction - - extra string -} - -// New block takes a raw encoded string -func NewBlock(raw []byte) *Block { - block := &Block{} - block.UnmarshalRlp(raw) - - return block -} - -// Creates a new block. This is currently for testing -func CreateTestBlock(/* TODO use raw data */transactions []*Transaction) *Block { - block := &Block{ - // Slice of transactions to include in this block - transactions: transactions, - number: 1, - prevHash: "1234", - coinbase: "me", - difficulty: 10, - nonce: 0, - time: time.Now().Unix(), - } - - return block -} - -func CreateBlock(root string, - num int, - prevHash string, - base string, - difficulty int, - nonce int, - extra string, - txes []*Transaction) *Block { - - block := &Block{ - // Slice of transactions to include in this block - transactions: txes, - number: uint32(num), - prevHash: prevHash, - coinbase: base, - difficulty: uint32(difficulty), - nonce: uint32(nonce), - time: time.Now().Unix(), - extra: extra, - } - block.state = NewTrie(Db, root) - - for _, tx := range txes { - // Create contract if there's no recipient - if tx.recipient == "" { - addr := tx.Hash() - - contract := NewContract(tx.value, []byte("")) - block.state.Update(string(addr), string(contract.MarshalRlp())) - for i, val := range tx.data { - contract.state.Update(string(NumberToBytes(uint64(i), 32)), val) - } - block.UpdateContract(addr, contract) - } - } - - return block -} - -func (block *Block) GetContract(addr []byte) *Contract { - data := block.state.Get(string(addr)) - if data == "" { - return nil - } - - contract := &Contract{} - contract.UnmarshalRlp([]byte(data)) - - return contract -} - -func (block *Block) UpdateContract(addr []byte, contract *Contract) { - block.state.Update(string(addr), string(contract.MarshalRlp())) -} - - -func (block *Block) PayFee(addr []byte, fee uint64) bool { - contract := block.GetContract(addr) - // If we can't pay the fee return - if contract == nil || contract.amount < fee { - fmt.Println("Contract has insufficient funds", contract.amount, fee) - - return false - } - - contract.amount -= fee - block.state.Update(string(addr), string(contract.MarshalRlp())) - - data := block.state.Get(string(block.coinbase)) - - // Get the ether (coinbase) and add the fee (gief fee to miner) - ether := NewEtherFromData([]byte(data)) - ether.amount += fee - - block.state.Update(string(block.coinbase), string(ether.MarshalRlp())) - - return true -} - -// Returns a hash of the block -func (block *Block) Hash() []byte { - return Sha256Bin(block.MarshalRlp()) -} - -func (block *Block) MarshalRlp() []byte { - // Marshal the transactions of this block - encTx := make([]string, len(block.transactions)) - for i, tx := range block.transactions { - // Cast it to a string (safe) - encTx[i] = string(tx.MarshalRlp()) - } - // TODO - uncles := []interface{}{} - - // I made up the block. It should probably contain different data or types. - // It sole purpose now is testing - header := []interface{}{ - block.number, - block.prevHash, - // Sha of uncles - "", - block.coinbase, - // root state - block.state.root, - // Sha of tx - string(Sha256Bin([]byte(Encode(encTx)))), - block.difficulty, - uint64(block.time), - block.nonce, - block.extra, - } - - // Encode a slice interface which contains the header and the list of - // transactions. - return Encode([]interface{}{header, encTx, uncles}) -} - -func (block *Block) UnmarshalRlp(data []byte) { - decoder := NewRlpDecoder(data) - - header := decoder.Get(0) - block.number = uint32(header.Get(0).AsUint()) - block.prevHash = header.Get(1).AsString() - // sha of uncles is header[2] - block.coinbase = header.Get(3).AsString() - block.state = NewTrie(Db, header.Get(4).AsString()) - block.difficulty = uint32(header.Get(5).AsUint()) - block.time = int64(header.Get(6).AsUint()) - block.nonce = uint32(header.Get(7).AsUint()) - block.extra = header.Get(8).AsString() - - txes := decoder.Get(1) - block.transactions = make([]*Transaction, txes.Length()) - for i := 0; i < txes.Length(); i++ { - tx := &Transaction{} - tx.UnmarshalRlp(txes.Get(i).AsBytes()) - block.transactions[i] = tx - } -} diff --git a/block_manager.go b/block_manager.go index 134ca0e75..59430dca7 100644 --- a/block_manager.go +++ b/block_manager.go @@ -2,17 +2,18 @@ package main import ( "fmt" + "github.com/ethereum/ethutil-go" ) type BlockChain struct { - lastBlock *Block + lastBlock *ethutil.Block - genesisBlock *Block + genesisBlock *ethutil.Block } func NewBlockChain() *BlockChain { bc := &BlockChain{} - bc.genesisBlock = NewBlock( Encode(Genesis) ) + bc.genesisBlock = ethutil.NewBlock( ethutil.Encode(ethutil.Genesis) ) return bc } @@ -30,19 +31,19 @@ func NewBlockManager() *BlockManager { } // Process a block. -func (bm *BlockManager) ProcessBlock(block *Block) error { +func (bm *BlockManager) ProcessBlock(block *ethutil.Block) error { // TODO Validation (Or move to other part of the application) if err := bm.ValidateBlock(block); err != nil { return err } // Get the tx count. Used to create enough channels to 'join' the go routines - txCount := len(block.transactions) + txCount := len(block.Transactions()) // Locking channel. When it has been fully buffered this method will return lockChan := make(chan bool, txCount) // Process each transaction/contract - for _, tx := range block.transactions { + for _, tx := range block.Transactions() { // If there's no recipient, it's a contract if tx.IsContract() { go bm.ProcessContract(tx, block, lockChan) @@ -60,11 +61,11 @@ func (bm *BlockManager) ProcessBlock(block *Block) error { return nil } -func (bm *BlockManager) ValidateBlock(block *Block) error { +func (bm *BlockManager) ValidateBlock(block *ethutil.Block) error { return nil } -func (bm *BlockManager) ProcessContract(tx *Transaction, block *Block, lockChan chan bool) { +func (bm *BlockManager) ProcessContract(tx *ethutil.Transaction, block *ethutil.Block, lockChan chan bool) { // Recovering function in case the VM had any errors defer func() { if r := recover(); r != nil { diff --git a/bytes.go b/bytes.go deleted file mode 100644 index 6bf381343..000000000 --- a/bytes.go +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "bytes" - "encoding/binary" - "fmt" -) - -func NumberToBytes(num uint64, bits int) []byte { - buf := new(bytes.Buffer) - err := binary.Write(buf, binary.BigEndian, num) - if err != nil { - fmt.Println("binary.Write failed:", err) - } - - return buf.Bytes()[buf.Len()-(bits / 8):] -} - -func BytesToNumber(b []byte) (number uint64) { - buf := bytes.NewReader(b) - err := binary.Read(buf, binary.LittleEndian, &number) - if err != nil { - fmt.Println("binary.Read failed:", err) - } - - return -} diff --git a/contract.go b/contract.go deleted file mode 100644 index a54643f59..000000000 --- a/contract.go +++ /dev/null @@ -1,65 +0,0 @@ -package main - -import ( - _"fmt" -) - -type Contract struct { - t uint32 // contract is always 1 - amount uint64 // ??? - state *Trie -} - -func NewContract(amount uint64, root []byte) *Contract { - contract := &Contract{t: 1, amount: amount} - contract.state = NewTrie(Db, string(root)) - - return contract -} - -func (c *Contract) MarshalRlp() []byte { - return Encode([]interface{}{c.t, c.amount, c.state.root}) -} - -func (c *Contract) UnmarshalRlp(data []byte) { - decoder := NewRlpDecoder(data) - - c.t = uint32(decoder.Get(0).AsUint()) - c.amount = decoder.Get(1).AsUint() - c.state = NewTrie(Db, decoder.Get(2).AsString()) -} - -type Ether struct { - t uint32 - amount uint64 - nonce string -} - -func NewEtherFromData(data []byte) *Ether { - ether := &Ether{} - ether.UnmarshalRlp(data) - - return ether -} - -func (e *Ether) MarshalRlp() []byte { - return Encode([]interface{}{e.t, e.amount, e.nonce}) -} - -func (e *Ether) UnmarshalRlp(data []byte) { - t, _ := Decode(data, 0) - - if slice, ok := t.([]interface{}); ok { - if t, ok := slice[0].(uint8); ok { - e.t = uint32(t) - } - - if amount, ok := slice[1].(uint8); ok { - e.amount = uint64(amount) - } - - if nonce, ok := slice[2].([]uint8); ok { - e.nonce = string(nonce) - } - } -} diff --git a/dagger.go b/dagger.go index 2c1976840..5aa5dd755 100644 --- a/dagger.go +++ b/dagger.go @@ -6,6 +6,7 @@ import ( "time" "github.com/obscuren/sha3" "hash" + "github.com/ethereum/ethutil-go" ) type Dagger struct { @@ -40,7 +41,7 @@ func (dag *Dagger) Search(hash, diff *big.Int) *big.Int { dag.hash = hash - obj := BigPow(2, 256) + obj := ethutil.BigPow(2, 256) obj = obj.Div(obj, diff) Found = false @@ -66,7 +67,7 @@ func DaggerVerify(hash, diff, nonce *big.Int) bool { dagger := &Dagger{} dagger.hash = hash - obj := BigPow(2, 256) + obj := ethutil.BigPow(2, 256) obj = obj.Div(obj, diff) return dagger.Eval(nonce).Cmp(obj) < 0 @@ -114,7 +115,7 @@ func Sum(sha hash.Hash) []byte { } func (dag *Dagger) Eval(N *big.Int) *big.Int { - pow := BigPow(2, 26) + pow := ethutil.BigPow(2, 26) dag.xn = N.Div(N, pow) sha := sha3.NewKeccak256() diff --git a/database.go b/database.go deleted file mode 100644 index b147756b6..000000000 --- a/database.go +++ /dev/null @@ -1,56 +0,0 @@ -package main - -import ( - "path" - "os/user" - "github.com/syndtr/goleveldb/leveldb" - "fmt" -) - -type LDBDatabase struct { - db *leveldb.DB - trie *Trie -} - -func NewLDBDatabase() (*LDBDatabase, error) { - // This will eventually have to be something like a resource folder. - // it works on my system for now. Probably won't work on Windows - usr, _ := user.Current() - dbPath := path.Join(usr.HomeDir, ".ethereum", "database") - - // Open the db - db, err := leveldb.OpenFile(dbPath, nil) - if err != nil { - return nil, err - } - - database := &LDBDatabase{db: db} - - // Bootstrap database. Sets a few defaults; such as the last block - database.Bootstrap() - - return database, nil -} - -func (db *LDBDatabase) Bootstrap() error { - //db.trie = NewTrie(db) - - return nil -} - -func (db *LDBDatabase) Put(key []byte, value []byte) { - err := db.db.Put(key, value, nil) - if err != nil { - fmt.Println("Error put", err) - } -} - -func (db *LDBDatabase) Get(key []byte) ([]byte, error) { - return nil, nil -} - -func (db *LDBDatabase) Close() { - // Close the leveldb database - db.db.Close() -} - diff --git a/database_test.go b/database_test.go deleted file mode 100644 index 1a46eb95e..000000000 --- a/database_test.go +++ /dev/null @@ -1,7 +0,0 @@ -package main - -import ( - _"testing" - _"fmt" -) - diff --git a/dev_console.go b/dev_console.go index 65166c0c1..27fc2e65e 100644 --- a/dev_console.go +++ b/dev_console.go @@ -7,16 +7,18 @@ import ( "os" "errors" "encoding/hex" + "github.com/ethereum/ethdb-go" + "github.com/ethereum/ethutil-go" ) type Console struct { - db *MemDatabase - trie *Trie + db *ethdb.MemDatabase + trie *ethutil.Trie } func NewConsole() *Console { - db, _ := NewMemDatabase() - trie := NewTrie(db, "") + db, _ := ethdb.NewMemDatabase() + trie := ethutil.NewTrie(db, "") return &Console{db: db, trie: trie} } @@ -68,17 +70,19 @@ func (i *Console) ParseInput(input string) bool { case "update": i.trie.Update(tokens[1], tokens[2]) - fmt.Println(hex.EncodeToString([]byte(i.trie.root))) + fmt.Println(hex.EncodeToString([]byte(i.trie.Root))) case "get": fmt.Println(i.trie.Get(tokens[1])) case "root": - fmt.Println(hex.EncodeToString([]byte(i.trie.root))) + fmt.Println(hex.EncodeToString([]byte(i.trie.Root))) case "rawroot": - fmt.Println(i.trie.root) + fmt.Println(i.trie.Root) case "print": i.db.Print() case "dag": - fmt.Println(DaggerVerify(Big(tokens[1]), BigPow(2, 36), Big(tokens[2]))) + fmt.Println(DaggerVerify( ethutil.Big(tokens[1]), // hash + ethutil.BigPow(2, 36), // diff + ethutil.Big(tokens[2])))// nonce case "exit", "quit", "q": return false case "help": diff --git a/encoding.go b/encoding.go deleted file mode 100644 index d77303817..000000000 --- a/encoding.go +++ /dev/null @@ -1,62 +0,0 @@ -package main - -import ( - "bytes" - "encoding/hex" - "strings" - _"fmt" -) - -func CompactEncode(hexSlice []int) string { - terminator := 0 - if hexSlice[len(hexSlice)-1] == 16 { - terminator = 1 - } - - if terminator == 1 { - hexSlice = hexSlice[:len(hexSlice)-1] - } - - oddlen := len(hexSlice) % 2 - flags := 2 * terminator + oddlen - if oddlen != 0 { - hexSlice = append([]int{flags}, hexSlice...) - } else { - hexSlice = append([]int{flags, 0}, hexSlice...) - } - - var buff bytes.Buffer - for i := 0; i < len(hexSlice); i+=2 { - buff.WriteByte(byte(16 * hexSlice[i] + hexSlice[i+1])) - } - - return buff.String() -} - -func CompactDecode(str string) []int { - base := CompactHexDecode(str) - base = base[:len(base)-1] - if base[0] >= 2 {// && base[len(base)-1] != 16 { - base = append(base, 16) - } - if base[0] % 2 == 1 { - base = base[1:] - } else { - base = base[2:] - } - - return base -} - -func CompactHexDecode(str string) []int { - base := "0123456789abcdef" - hexSlice := make([]int, 0) - - enc := hex.EncodeToString([]byte(str)) - for _, v := range enc { - hexSlice = append(hexSlice, strings.IndexByte(base, byte(v))) - } - hexSlice = append(hexSlice, 16) - - return hexSlice -} diff --git a/encoding_test.go b/encoding_test.go deleted file mode 100644 index b66f702ac..000000000 --- a/encoding_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package main - -import ( - "testing" - "fmt" -) - -func TestCompactEncode(t *testing.T) { - test1 := []int{1,2,3,4,5} - if res := CompactEncode(test1); res != "\x11\x23\x45" { - t.Error(fmt.Sprintf("even compact encode failed. Got: %q", res)) - } - - test2 := []int{0, 1, 2, 3, 4, 5} - if res := CompactEncode(test2); res != "\x00\x01\x23\x45" { - t.Error(fmt.Sprintf("odd compact encode failed. Got: %q", res)) - } - - test3 := []int{0, 15, 1, 12, 11, 8, /*term*/16} - if res := CompactEncode(test3); res != "\x20\x0f\x1c\xb8" { - t.Error(fmt.Sprintf("odd terminated compact encode failed. Got: %q", res)) - } - - test4 := []int{15, 1, 12, 11, 8, /*term*/16} - if res := CompactEncode(test4); res != "\x3f\x1c\xb8" { - t.Error(fmt.Sprintf("even terminated compact encode failed. Got: %q", res)) - } -} - - -func TestCompactHexDecode(t *testing.T) { - exp := []int{7, 6, 6, 5, 7, 2, 6, 2, 16} - res := CompactHexDecode("verb") - - if !CompareIntSlice(res, exp) { - t.Error("Error compact hex decode. Expected", exp, "got", res) - } -} diff --git a/ethereum.go b/ethereum.go index aee8ebc30..96b67f970 100644 --- a/ethereum.go +++ b/ethereum.go @@ -7,7 +7,7 @@ import ( "flag" "runtime" "log" - _"math/big" + "github.com/ethereum/ethutil-go" ) const Debug = true @@ -39,7 +39,7 @@ func RegisterInterupts(s *Server) { func main() { runtime.GOMAXPROCS(runtime.NumCPU()) - InitFees() + ethutil.InitFees() Init() @@ -63,7 +63,7 @@ func main() { go func() { for { - res := dagger.Search(Big("0"), BigPow(2, 36)) + res := dagger.Search(ethutil.Big("0"), ethutil.BigPow(2, 36)) server.Broadcast("block", Encode(res.String())) } }() diff --git a/genesis.go b/genesis.go deleted file mode 100644 index 21b8e9998..000000000 --- a/genesis.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "math" -) - -/* - * This is the special genesis block. - */ - -var GenisisHeader = []interface{}{ - // Block number - uint32(0), - // Previous hash (none) - "", - // Sha of uncles - string(Sha256Bin(Encode([]interface{}{}))), - // Coinbase - "", - // Root state - "", - // Sha of transactions - string(Sha256Bin(Encode([]interface{}{}))), - // Difficulty - uint32(math.Pow(2, 36)), - // Time - uint64(1), - // Nonce - uint32(0), - // Extra - "", -} - -var Genesis = []interface{}{ GenisisHeader, []interface{}{}, []interface{}{} } diff --git a/memory_database.go b/memory_database.go deleted file mode 100644 index a8c74bb46..000000000 --- a/memory_database.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "fmt" -) - -/* - * This is a test memory database. Do not use for any production it does not get persisted - */ -type MemDatabase struct { - db map[string][]byte -} - -func NewMemDatabase() (*MemDatabase, error) { - db := &MemDatabase{db: make(map[string][]byte)} - - return db, nil -} - -func (db *MemDatabase) Put(key []byte, value []byte) { - db.db[string(key)] = value -} - -func (db *MemDatabase) Get(key []byte) ([]byte, error) { - return db.db[string(key)], nil -} - -func (db *MemDatabase) Print() { - for key, val := range db.db { - fmt.Printf("%x(%d):", key, len(key)) - decoded := DecodeNode(val) - PrintSlice(decoded) - } -} diff --git a/parsing.go b/parsing.go deleted file mode 100644 index b97d77f3e..000000000 --- a/parsing.go +++ /dev/null @@ -1,98 +0,0 @@ -package main - -import ( - "fmt" - "strings" - "errors" - "math/big" - "strconv" -) - -// Op codes -var OpCodes = map[string]string{ - "STOP": "0", - "ADD": "1", - "MUL": "2", - "SUB": "3", - "DIV": "4", - "SDIV": "5", - "MOD": "6", - "SMOD": "7", - "EXP": "8", - "NEG": "9", - "LT": "10", - "LE": "11", - "GT": "12", - "GE": "13", - "EQ": "14", - "NOT": "15", - "MYADDRESS": "16", - "TXSENDER": "17", - - - "PUSH": "48", - "POP": "49", - "LOAD": "54", -} - - -func CompileInstr(s string) (string, error) { - tokens := strings.Split(s, " ") - if OpCodes[tokens[0]] == "" { - return s, errors.New(fmt.Sprintf("OP not found: %s", tokens[0])) - } - - code := OpCodes[tokens[0]] // Replace op codes with the proper numerical equivalent - op := new(big.Int) - op.SetString(code, 0) - - args := make([]*big.Int, 6) - for i, val := range tokens[1:len(tokens)] { - num := new(big.Int) - num.SetString(val, 0) - args[i] = num - } - - // Big int equation = op + x * 256 + y * 256**2 + z * 256**3 + a * 256**4 + b * 256**5 + c * 256**6 - base := new(big.Int) - x := new(big.Int) - y := new(big.Int) - z := new(big.Int) - a := new(big.Int) - b := new(big.Int) - c := new(big.Int) - - if args[0] != nil { x.Mul(args[0], big.NewInt(256)) } - if args[1] != nil { y.Mul(args[1], BigPow(256, 2)) } - if args[2] != nil { z.Mul(args[2], BigPow(256, 3)) } - if args[3] != nil { a.Mul(args[3], BigPow(256, 4)) } - if args[4] != nil { b.Mul(args[4], BigPow(256, 5)) } - if args[5] != nil { c.Mul(args[5], BigPow(256, 6)) } - - base.Add(op, x) - base.Add(base, y) - base.Add(base, z) - base.Add(base, a) - base.Add(base, b) - base.Add(base, c) - - return base.String(), nil -} - -func Instr(instr string) (int, []string, error) { - base := new(big.Int) - base.SetString(instr, 0) - - args := make([]string, 7) - for i := 0; i < 7; i++ { - // int(int(val) / int(math.Pow(256,float64(i)))) % 256 - exp := BigPow(256, i) - num := new(big.Int) - num.Div(base, exp) - - args[i] = num.Mod(num, big.NewInt(256)).String() - } - op, _ := strconv.Atoi(args[0]) - - return op, args[1:7], nil -} diff --git a/parsing_test.go b/parsing_test.go deleted file mode 100644 index 6aa9e240c..000000000 --- a/parsing_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package main - -import ( - "testing" - "math" -) - -func TestCompile(t *testing.T) { - instr, err := CompileInstr("PUSH") - - if err != nil { - t.Error("Failed compiling instruction") - } - - calc := (48 + 0 * 256 + 0 * int64(math.Pow(256,2))) - if Big(instr).Int64() != calc { - t.Error("Expected", calc, ", got:", instr) - } -} - -func TestValidInstr(t *testing.T) { - /* - op, args, err := Instr("68163") - if err != nil { - t.Error("Error decoding instruction") - } - */ - -} - -func TestInvalidInstr(t *testing.T) { -} - diff --git a/rlp.go b/rlp.go index 5366632f4..cee9da613 100644 --- a/rlp.go +++ b/rlp.go @@ -5,6 +5,7 @@ import ( "bytes" "math" "math/big" + "github.com/ethereum/ethutil-go" ) type RlpEncoder struct { @@ -54,7 +55,7 @@ func (attr *RlpDataAttribute) AsUint() uint64 { func (attr *RlpDataAttribute) AsBigInt() *big.Int { if a, ok := attr.dataAttrib.([]byte); ok { - return Big(string(a)) + return ethutil.Big(string(a)) } return big.NewInt(0) diff --git a/server.go b/server.go index c2903cb59..d81fe1bce 100644 --- a/server.go +++ b/server.go @@ -5,15 +5,15 @@ import ( "net" "log" _"time" + "github.com/ethereum/ethdb-go" + "github.com/ethereum/ethutil-go" ) -var Db *LDBDatabase - type Server struct { // Channel for shutting down the server shutdownChan chan bool // DB interface - db *LDBDatabase + db *ethdb.LDBDatabase // Block manager for processing new blocks and managing the block chain blockManager *BlockManager // Peers (NYI) @@ -21,12 +21,12 @@ type Server struct { } func NewServer() (*Server, error) { - db, err := NewLDBDatabase() + db, err := ethdb.NewLDBDatabase() if err != nil { return nil, err } - Db = db + ethutil.SetConfig(db) server := &Server{ shutdownChan: make(chan bool), diff --git a/transaction.go b/transaction.go deleted file mode 100644 index 90e0d9869..000000000 --- a/transaction.go +++ /dev/null @@ -1,206 +0,0 @@ -package main - -import ( - "math/big" - "fmt" - "github.com/obscuren/secp256k1-go" - _"encoding/hex" - _"crypto/sha256" - _ "bytes" -) - -/* -Transaction Contract Size -------------------------------------------- -sender sender 20 bytes -recipient 0x0 20 bytes -value endowment 4 bytes (uint32) -fee fee 4 bytes (uint32) -d_size o_size 4 bytes (uint32) -data ops * -signature signature 64 bytes -*/ - -var StepFee *big.Int = new(big.Int) -var TxFee *big.Int = new(big.Int) -var ContractFee *big.Int = new(big.Int) -var MemFee *big.Int = new(big.Int) -var DataFee *big.Int = new(big.Int) -var CryptoFee *big.Int = new(big.Int) -var ExtroFee *big.Int = new(big.Int) - -var Period1Reward *big.Int = new(big.Int) -var Period2Reward *big.Int = new(big.Int) -var Period3Reward *big.Int = new(big.Int) -var Period4Reward *big.Int = new(big.Int) - -type Transaction struct { - nonce string - sender string - recipient string - value uint64 - fee uint32 - data []string - memory []int - lastTx string - v uint32 - r, s []byte -} - -func NewTransaction(to string, value uint64, data []string) *Transaction { - tx := Transaction{sender: "1234567890", recipient: to, value: value} - tx.nonce = "0" - tx.fee = 0//uint32((ContractFee + MemoryFee * float32(len(tx.data))) * 1e8) - tx.lastTx = "0" - - // Serialize the data - tx.data = make([]string, len(data)) - for i, val := range data { - instr, err := CompileInstr(val) - if err != nil { - //fmt.Printf("compile error:%d %v\n", i+1, err) - } - - tx.data[i] = instr - } - - tx.Sign([]byte("privkey")) - tx.Sender() - - - return &tx -} - -func (tx *Transaction) Hash() []byte { - preEnc := []interface{}{ - tx.nonce, - tx.recipient, - tx.value, - tx.fee, - tx.data, - } - - return Sha256Bin(Encode(preEnc)) -} - -func (tx *Transaction) IsContract() bool { - return tx.recipient == "" -} - -func (tx *Transaction) Signature(key []byte) []byte { - hash := tx.Hash() - sec := Sha256Bin(key) - - sig, _ := secp256k1.Sign(hash, sec) - - return sig -} - -func (tx *Transaction) PublicKey() []byte { - hash := Sha256Bin(tx.Hash()) - sig := append(tx.r, tx.s...) - - pubkey, _ := secp256k1.RecoverPubkey(hash, sig) - - return pubkey -} - -func (tx *Transaction) Sender() []byte { - pubkey := tx.PublicKey() - - // Validate the returned key. - // Return nil if public key isn't in full format (04 = full, 03 = compact) - if pubkey[0] != 4 { - return nil - } - - return Sha256Bin(pubkey[1:65])[12:] -} - -func (tx *Transaction) Sign(privk []byte) { - sig := tx.Signature(privk) - - // Add 27 so we get either 27 or 28 (for positive and negative) - tx.v = uint32(sig[64]) + 27 - tx.r = sig[:32] - tx.s = sig[32:65] -} - -func (tx *Transaction) MarshalRlp() []byte { - // Prepare the transaction for serialization - preEnc := []interface{}{ - tx.nonce, - tx.recipient, - tx.value, - tx.fee, - tx.data, - tx.v, - tx.r, - tx.s, - } - - return Encode(preEnc) -} - -func (tx *Transaction) UnmarshalRlp(data []byte) { - decoder := NewRlpDecoder(data) - - tx.nonce = decoder.Get(0).AsString() - tx.recipient = decoder.Get(0).AsString() - tx.value = decoder.Get(2).AsUint() - tx.fee = uint32(decoder.Get(3).AsUint()) - - d := decoder.Get(4) - tx.data = make([]string, d.Length()) - fmt.Println(d.Get(0)) - for i := 0; i < d.Length(); i++ { - tx.data[i] = d.Get(i).AsString() - } - - tx.v = uint32(decoder.Get(5).AsUint()) - tx.r = decoder.Get(6).AsBytes() - tx.s = decoder.Get(7).AsBytes() -} - -func InitFees() { - // Base for 2**60 - b60 := new(big.Int) - b60.Exp(big.NewInt(2), big.NewInt(64), big.NewInt(0)) - // Base for 2**80 - b80 := new(big.Int) - b80.Exp(big.NewInt(2), big.NewInt(80), big.NewInt(0)) - - StepFee.Exp(big.NewInt(10), big.NewInt(16), big.NewInt(0)) - //StepFee.Div(b60, big.NewInt(64)) - //fmt.Println("StepFee:", StepFee) - - TxFee.Exp(big.NewInt(2), big.NewInt(64), big.NewInt(0)) - //fmt.Println("TxFee:", TxFee) - - ContractFee.Exp(big.NewInt(2), big.NewInt(64), big.NewInt(0)) - //fmt.Println("ContractFee:", ContractFee) - - MemFee.Div(b60, big.NewInt(4)) - //fmt.Println("MemFee:", MemFee) - - DataFee.Div(b60, big.NewInt(16)) - //fmt.Println("DataFee:", DataFee) - - CryptoFee.Div(b60, big.NewInt(16)) - //fmt.Println("CrytoFee:", CryptoFee) - - ExtroFee.Div(b60, big.NewInt(16)) - //fmt.Println("ExtroFee:", ExtroFee) - - Period1Reward.Mul(b80, big.NewInt(1024)) - //fmt.Println("Period1Reward:", Period1Reward) - - Period2Reward.Mul(b80, big.NewInt(512)) - //fmt.Println("Period2Reward:", Period2Reward) - - Period3Reward.Mul(b80, big.NewInt(256)) - //fmt.Println("Period3Reward:", Period3Reward) - - Period4Reward.Mul(b80, big.NewInt(128)) - //fmt.Println("Period4Reward:", Period4Reward) -} diff --git a/trie.go b/trie.go deleted file mode 100644 index d66699eeb..000000000 --- a/trie.go +++ /dev/null @@ -1,203 +0,0 @@ -package main - -import ( - "fmt" -) - -// Database interface -type Database interface { - Put(key []byte, value []byte) - Get(key []byte) ([]byte, error) -} - -/* - * Trie helper functions - */ -// Helper function for printing out the raw contents of a slice -func PrintSlice(slice []string) { - fmt.Printf("[") - for i, val := range slice { - fmt.Printf("%q", val) - if i != len(slice)-1 { fmt.Printf(",") } - } - fmt.Printf("]\n") -} - -// RLP Decodes a node in to a [2] or [17] string slice -func DecodeNode(data []byte) []string { - dec, _ := Decode(data, 0) - if slice, ok := dec.([]interface{}); ok { - strSlice := make([]string, len(slice)) - - for i, s := range slice { - if str, ok := s.([]byte); ok { - strSlice[i] = string(str) - } - } - - return strSlice - } else { - fmt.Printf("It wasn't a []. It's a %T\n", dec) - } - - return nil -} - -// A (modified) Radix Trie implementation -type Trie struct { - root string - db Database -} - -func NewTrie(db Database, root string) *Trie { - return &Trie{db: db, root: root} -} - -/* - * Public (query) interface functions - */ -func (t *Trie) Update(key string, value string) { - k := CompactHexDecode(key) - - t.root = t.UpdateState(t.root, k, value) -} - -func (t *Trie) Get(key string) string { - k := CompactHexDecode(key) - - return t.GetState(t.root, k) -} - -/* - * State functions (shouldn't be needed directly). - */ - -// Helper function for printing a node (using fetch, decode and slice printing) -func (t *Trie) PrintNode(n string) { - data, _ := t.db.Get([]byte(n)) - d := DecodeNode(data) - PrintSlice(d) -} - -// Returns the state of an object -func (t *Trie) GetState(node string, key []int) string { - // Return the node if key is empty (= found) - if len(key) == 0 || node == "" { - return node - } - - // Fetch the encoded node from the db - n, err := t.db.Get([]byte(node)) - if err != nil { fmt.Println("Error in GetState for node", node, "with key", key); return "" } - - // Decode it - currentNode := DecodeNode(n) - - if len(currentNode) == 0 { - return "" - } else if len(currentNode) == 2 { - // Decode the key - k := CompactDecode(currentNode[0]) - v := currentNode[1] - - if len(key) >= len(k) && CompareIntSlice(k, key[:len(k)]) { - return t.GetState(v, key[len(k):]) - } else { - return "" - } - } else if len(currentNode) == 17 { - return t.GetState(currentNode[key[0]], key[1:]) - } - - // It shouldn't come this far - fmt.Println("GetState unexpected return") - return "" -} - -// Inserts a new sate or delete a state based on the value -func (t *Trie) UpdateState(node string, key []int, value string) string { - if value != "" { - return t.InsertState(node, key, value) - } else { - // delete it - } - - return "" -} - -// Wrapper around the regular db "Put" which generates a key and value -func (t *Trie) Put(node interface{}) []byte { - enc := Encode(node) - var sha []byte - sha = Sha256Bin(enc) - - t.db.Put([]byte(sha), enc) - - return sha -} - -func (t *Trie) InsertState(node string, key []int, value string) string { - if len(key) == 0 { - return value - } - - // New node - if node == "" { - newNode := []string{ CompactEncode(key), value } - - return string(t.Put(newNode)) - } - - // Fetch the encoded node from the db - n, err := t.db.Get([]byte(node)) - if err != nil { fmt.Println("Error InsertState", err); return "" } - - // Decode it - currentNode := DecodeNode(n) - // Check for "special" 2 slice type node - if len(currentNode) == 2 { - // Decode the key - k := CompactDecode(currentNode[0]) - v := currentNode[1] - - // Matching key pair (ie. there's already an object with this key) - if CompareIntSlice(k, key) { - return string(t.Put([]string{ CompactEncode(key), value })) - } - - var newHash string - matchingLength := MatchingNibbleLength(key, k) - if matchingLength == len(k) { - // Insert the hash, creating a new node - newHash = t.InsertState(v, key[matchingLength:], value) - } else { - // Expand the 2 length slice to a 17 length slice - oldNode := t.InsertState("", k[matchingLength+1:], v) - newNode := t.InsertState("", key[matchingLength+1:], value) - // Create an expanded slice - scaledSlice := make([]string, 17) - // Set the copied and new node - scaledSlice[k[matchingLength]] = oldNode - scaledSlice[key[matchingLength]] = newNode - - newHash = string(t.Put(scaledSlice)) - } - - if matchingLength == 0 { - // End of the chain, return - return newHash - } else { - newNode := []string{ CompactEncode(key[:matchingLength]), newHash } - return string(t.Put(newNode)) - } - } else { - // Copy the current node over to the new node and replace the first nibble in the key - newNode := make([]string, 17); copy(newNode, currentNode) - newNode[key[0]] = t.InsertState(currentNode[key[0]], key[1:], value) - - return string(t.Put(newNode)) - } - - return "" -} - diff --git a/trie_test.go b/trie_test.go deleted file mode 100644 index 599a5f47c..000000000 --- a/trie_test.go +++ /dev/null @@ -1,59 +0,0 @@ -package main - -import ( - "testing" - "encoding/hex" - _"fmt" -) - -func TestTriePut(t *testing.T) { - db, err := NewMemDatabase() - trie := NewTrie(db, "") - - if err != nil { - t.Error("Error starting db") - } - - key := trie.Put([]byte("testing node")) - - data, err := db.Get(key) - if err != nil { - t.Error("Nothing at node") - } - - s, _ := Decode(data, 0) - if str, ok := s.([]byte); ok { - if string(str) != "testing node" { - t.Error("Wrong value node", str) - } - } else { - t.Error("Invalid return type") - } -} - -func TestTrieUpdate(t *testing.T) { - db, err := NewMemDatabase() - trie := NewTrie(db, "") - - if err != nil { - t.Error("Error starting db") - } - - - trie.Update("doe", "reindeer") - trie.Update("dog", "puppy") - /* - data, _ := db.Get([]byte(trie.root)) - data, _ = db.Get([]byte(DecodeNode(data)[1])) - data, _ = db.Get([]byte(DecodeNode(data)[7])) - PrintSlice(DecodeNode(data)) - */ - - trie.Update("dogglesworth", "cat") - root := hex.EncodeToString([]byte(trie.root)) - req := "e378927bfc1bd4f01a2e8d9f59bd18db8a208bb493ac0b00f93ce51d4d2af76c" - if root != req { - t.Error("trie.root do not match, expected", req, "got", root) - } -} - diff --git a/util.go b/util.go deleted file mode 100644 index 24e5455f4..000000000 --- a/util.go +++ /dev/null @@ -1,63 +0,0 @@ -package main - -import ( - "strconv" - "crypto/sha256" - "encoding/hex" - _"fmt" - _"math" - "github.com/obscuren/sha3" -) - -func Uitoa(i uint32) string { - return strconv.FormatUint(uint64(i), 10) -} - -func Sha256Hex(data []byte) string { - hash := sha256.Sum256(data) - - return hex.EncodeToString(hash[:]) -} - -func Sha256Bin(data []byte) []byte { - hash := sha256.Sum256(data) - - return hash[:] -} - -func Sha3Bin(data []byte) []byte { - d := sha3.NewKeccak224() - d.Reset() - d.Write(data) - - return d.Sum(nil) -} - -// Helper function for comparing slices -func CompareIntSlice(a, b []int) bool { - if len(a) != len(b) { - return false - } - for i, v := range a { - if v != b[i] { - return false - } - } - return true -} - -// Returns the amount of nibbles that match each other from 0 ... -func MatchingNibbleLength(a, b []int) int { - i := 0 - for CompareIntSlice(a[:i+1], b[:i+1]) && i < len(b) { - i+=1 - } - - //fmt.Println(a, b, i-1) - - return i -} - -func Hex(d []byte) string { - return hex.EncodeToString(d) -} diff --git a/vm.go b/vm.go index 5b70f3544..5605cb7c7 100644 --- a/vm.go +++ b/vm.go @@ -1,12 +1,10 @@ package main import ( - _"math" "math/big" "fmt" - _"strconv" - _ "encoding/hex" "strconv" + "github.com/ethereum/ethutil-go" ) // Op codes @@ -93,7 +91,7 @@ func (st *Stack) Popn() (*big.Int, *big.Int) { strs := st.data[s-2:] st.data = st.data[:s-2] - return Big(strs[0]), Big(strs[1]) + return ethutil.Big(strs[0]), ethutil.Big(strs[1]) } func (st *Stack) Push(d string) { @@ -114,7 +112,8 @@ func NewVm() *Vm { } } -func (vm *Vm) ProcContract(tx *Transaction, block *Block, cb TxCallback) { +func (vm *Vm) ProcContract( tx *ethutil.Transaction, + block *ethutil.Block, cb TxCallback) { // Instruction pointer pc := 0 @@ -124,7 +123,7 @@ func (vm *Vm) ProcContract(tx *Transaction, block *Block, cb TxCallback) { return } - Pow256 := BigPow(2, 256) + Pow256 := ethutil.BigPow(2, 256) //fmt.Printf("# op arg\n") out: @@ -134,7 +133,8 @@ out: // XXX Should Instr return big int slice instead of string slice? // Get the next instruction from the contract //op, _, _ := Instr(contract.state.Get(string(Encode(uint32(pc))))) - op, _, _ := Instr(contract.state.Get(string(NumberToBytes(uint64(pc), 32)))) + nb := ethutil.NumberToBytes(uint64(pc), 32) + op, _, _ := ethutil.Instr(contract.State().Get(string(nb))) if !cb(0) { break } @@ -200,7 +200,7 @@ out: vm.stack.Push(base.String()) case oNEG: - base.Sub(Pow256, Big(vm.stack.Pop())) + base.Sub(Pow256, ethutil.Big(vm.stack.Pop())) vm.stack.Push(base.String()) case oLT: x, y := vm.stack.Popn() @@ -245,18 +245,18 @@ out: case oMYADDRESS: vm.stack.Push(string(tx.Hash())) case oTXSENDER: - vm.stack.Push(tx.sender) + vm.stack.Push(string(tx.Sender())) case oPUSH: // Get the next entry and pushes the value on the stack pc++ - vm.stack.Push(contract.state.Get(string(NumberToBytes(uint64(pc), 32)))) + vm.stack.Push(contract.State().Get(string(ethutil.NumberToBytes(uint64(pc), 32)))) case oPOP: // Pop current value of the stack vm.stack.Pop() case oLOAD: // Load instruction X on the stack i, _ := strconv.Atoi(vm.stack.Pop()) - vm.stack.Push(contract.state.Get(string(NumberToBytes(uint64(i), 32)))) + vm.stack.Push(contract.State().Get(string(ethutil.NumberToBytes(uint64(i), 32)))) case oSTOP: break out } -- cgit v1.2.3