aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-01-09 06:42:11 +0800
committerobscuren <geffobscura@gmail.com>2014-01-09 06:42:11 +0800
commit0929f59ec260e2a29863b8764959b271a7f75cc8 (patch)
tree42c76016d6f3030594604e6aabc5c4c01eb75519
parent9f133a92d0853102863b77dd7c884d1462cf73a4 (diff)
downloaddexon-0929f59ec260e2a29863b8764959b271a7f75cc8.tar
dexon-0929f59ec260e2a29863b8764959b271a7f75cc8.tar.gz
dexon-0929f59ec260e2a29863b8764959b271a7f75cc8.tar.bz2
dexon-0929f59ec260e2a29863b8764959b271a7f75cc8.tar.lz
dexon-0929f59ec260e2a29863b8764959b271a7f75cc8.tar.xz
dexon-0929f59ec260e2a29863b8764959b271a7f75cc8.tar.zst
dexon-0929f59ec260e2a29863b8764959b271a7f75cc8.zip
Updated marshalling
-rw-r--r--block.go93
-rw-r--r--contract.go24
-rw-r--r--genesis.go2
-rw-r--r--rlp.go105
-rw-r--r--transaction.go120
5 files changed, 168 insertions, 176 deletions
diff --git a/block.go b/block.go
index 00317573c..6ae3cc832 100644
--- a/block.go
+++ b/block.go
@@ -74,7 +74,6 @@ func CreateBlock(root string, num int, prevHash string, base string, difficulty
block.state.Update(string(addr), string(contract.MarshalRlp()))
for i, val := range tx.data {
contract.state.Update(string(NumberToBytes(uint64(i), 32)), val)
- //contract.state.Update(string(Encode(uint32(i))), val)
}
block.UpdateContract(addr, contract)
}
@@ -105,6 +104,7 @@ func (block *Block) PayFee(addr []byte, fee uint64) bool {
// 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
}
@@ -112,7 +112,7 @@ func (block *Block) PayFee(addr []byte, fee uint64) bool {
block.state.Update(string(addr), string(contract.MarshalRlp()))
data := block.state.Get(string(block.coinbase))
- println(data)
+
// Get the ether (coinbase) and add the fee (gief fee to miner)
ether := NewEtherFromData([]byte(data))
ether.amount += fee
@@ -159,75 +159,24 @@ func (block *Block) MarshalRlp() []byte {
}
func (block *Block) UnmarshalRlp(data []byte) {
- t, _ := Decode(data,0)
-
- // interface slice assertion
- if slice, ok := t.([]interface{}); ok {
- // interface slice assertion
- if header, ok := slice[0].([]interface{}); ok {
- if number, ok := header[0].(uint8); ok {
- block.number = uint32(number)
- }
-
- if prevHash, ok := header[1].([]uint8); ok {
- block.prevHash = string(prevHash)
- }
-
- // sha of uncles is header[2]
-
- if coinbase, ok := header[3].([]byte); ok {
- block.coinbase = string(coinbase)
- }
-
- if state, ok := header[4].([]uint8); ok {
- // XXX The database is currently a global variable defined in testing.go
- // This will eventually go away and the database will grabbed from the public server
- // interface
- block.state = NewTrie(Db, string(state))
- }
-
- // sha is header[5]
-
- // It's either 8bit or 64
- if difficulty, ok := header[6].(uint8); ok {
- block.difficulty = uint32(difficulty)
- }
- if difficulty, ok := header[6].(uint64); ok {
- block.difficulty = uint32(difficulty)
- }
-
- // It's either 8bit or 64
- if time, ok := header[7].(uint8); ok {
- block.time = int64(time)
- }
- if time, ok := header[7].(uint64); ok {
- block.time = int64(time)
- }
-
- if nonce, ok := header[8].(uint8); ok {
- block.nonce = uint32(nonce)
- }
-
- if extra, ok := header[9].([]byte); ok {
- block.extra = string(extra)
- }
- }
-
- if txSlice, ok := slice[1].([]interface{}); ok {
- // Create transaction slice equal to decoded tx interface slice
- block.transactions = make([]*Transaction, len(txSlice))
-
- // Unmarshal transactions
- for i, tx := range txSlice {
- if t, ok := tx.([]byte); ok {
- tx := &Transaction{}
- // Use the unmarshaled data to unmarshal the transaction
- // t is still decoded.
- tx.UnmarshalRlp(t)
-
- block.transactions[i] = tx
- }
- }
- }
+ 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/contract.go b/contract.go
index 778f3578d..a54643f59 100644
--- a/contract.go
+++ b/contract.go
@@ -22,27 +22,11 @@ func (c *Contract) MarshalRlp() []byte {
}
func (c *Contract) UnmarshalRlp(data []byte) {
- t, _ := Decode(data, 0)
-
- if slice, ok := t.([]interface{}); ok {
- if t, ok := slice[0].(uint8); ok {
- c.t = uint32(t)
- }
+ decoder := NewRlpDecoder(data)
- if amount, ok := slice[1].(uint8); ok {
- c.amount = uint64(amount)
- } else if amount, ok := slice[1].(uint16); ok {
- c.amount = uint64(amount)
- } else if amount, ok := slice[1].(uint32); ok {
- c.amount = uint64(amount)
- } else if amount, ok := slice[1].(uint64); ok {
- c.amount = amount
- }
-
- if root, ok := slice[2].([]uint8); ok {
- c.state = NewTrie(Db, string(root))
- }
- }
+ c.t = uint32(decoder.Get(0).AsUint())
+ c.amount = decoder.Get(1).AsUint()
+ c.state = NewTrie(Db, decoder.Get(2).AsString())
}
type Ether struct {
diff --git a/genesis.go b/genesis.go
index aae9cd1cf..21b8e9998 100644
--- a/genesis.go
+++ b/genesis.go
@@ -32,5 +32,3 @@ var GenisisHeader = []interface{}{
}
var Genesis = []interface{}{ GenisisHeader, []interface{}{}, []interface{}{} }
-
-var GenisisBlock = NewBlock( Encode(Genesis) )
diff --git a/rlp.go b/rlp.go
index 4db88539d..5366632f4 100644
--- a/rlp.go
+++ b/rlp.go
@@ -4,8 +4,110 @@ import (
"fmt"
"bytes"
"math"
+ "math/big"
)
+type RlpEncoder struct {
+ rlpData []byte
+}
+func NewRlpEncoder() *RlpEncoder {
+ encoder := &RlpEncoder{}
+
+ return encoder
+}
+func (coder *RlpEncoder) EncodeData(rlpData []interface{}) []byte {
+ return nil
+}
+
+// Data attributes are returned by the rlp decoder. The data attributes represents
+// one item within the rlp data structure. It's responsible for all the casting
+// It always returns something valid
+type RlpDataAttribute struct {
+ dataAttrib interface{}
+}
+
+func NewRlpDataAttribute(attrib interface{}) *RlpDataAttribute {
+ return &RlpDataAttribute{dataAttrib: attrib}
+}
+
+func (attr *RlpDataAttribute) Length() int {
+ if data, ok := attr.dataAttrib.([]interface{}); ok {
+ return len(data)
+ }
+
+ return 0
+}
+
+func (attr *RlpDataAttribute) AsUint() uint64 {
+ if value, ok := attr.dataAttrib.(uint8); ok {
+ return uint64(value)
+ } else if value, ok := attr.dataAttrib.(uint16); ok {
+ return uint64(value)
+ } else if value, ok := attr.dataAttrib.(uint32); ok {
+ return uint64(value)
+ } else if value, ok := attr.dataAttrib.(uint64); ok {
+ return value
+ }
+
+ return 0
+}
+
+func (attr *RlpDataAttribute) AsBigInt() *big.Int {
+ if a, ok := attr.dataAttrib.([]byte); ok {
+ return Big(string(a))
+ }
+
+ return big.NewInt(0)
+}
+
+func (attr *RlpDataAttribute) AsString() string {
+ if a, ok := attr.dataAttrib.([]byte); ok {
+ return string(a)
+ }
+
+ return ""
+}
+
+func (attr *RlpDataAttribute) AsBytes() []byte {
+ if a, ok := attr.dataAttrib.([]byte); ok {
+ return a
+ }
+
+ return make([]byte, 0)
+}
+
+// Threat the attribute as a slice
+func (attr *RlpDataAttribute) Get(idx int) *RlpDataAttribute {
+ if d, ok := attr.dataAttrib.([]interface{}); ok {
+ // Guard for oob
+ if len(d) < idx {
+ return NewRlpDataAttribute(nil)
+ }
+
+ return NewRlpDataAttribute(d[idx])
+ }
+
+ // If this wasn't a slice you probably shouldn't be using this function
+ return NewRlpDataAttribute(nil)
+}
+
+type RlpDecoder struct {
+ rlpData interface{}
+}
+func NewRlpDecoder(rlpData []byte) *RlpDecoder {
+ decoder := &RlpDecoder{}
+ // Decode the data
+ data, _ := Decode(rlpData,0)
+ decoder.rlpData = data
+
+ return decoder
+}
+
+func (dec *RlpDecoder) Get(idx int) *RlpDataAttribute {
+ return NewRlpDataAttribute(dec.rlpData).Get(idx)
+}
+
+/// Raw methods
func BinaryLength(n uint64) uint64 {
if n == 0 { return 0 }
@@ -122,6 +224,9 @@ func Encode(object interface{}) []byte {
buff.WriteString(string(len(b2) + 55) + b2 + b)
}
+ case *big.Int:
+ buff.Write(Encode(t.String()))
+
case string:
if len(t) < 56 {
buff.WriteString(string(len(t) + 64) + t)
diff --git a/transaction.go b/transaction.go
index 168d58566..90e0d9869 100644
--- a/transaction.go
+++ b/transaction.go
@@ -2,7 +2,7 @@ package main
import (
"math/big"
- _"fmt"
+ "fmt"
"github.com/obscuren/secp256k1-go"
_"encoding/hex"
_"crypto/sha256"
@@ -64,7 +64,8 @@ func NewTransaction(to string, value uint64, data []string) *Transaction {
tx.data[i] = instr
}
- tx.SetVRS()
+ tx.Sign([]byte("privkey"))
+ tx.Sender()
return &tx
@@ -86,9 +87,9 @@ func (tx *Transaction) IsContract() bool {
return tx.recipient == ""
}
-func (tx *Transaction) Signature() []byte {
+func (tx *Transaction) Signature(key []byte) []byte {
hash := tx.Hash()
- sec := Sha256Bin([]byte("myprivkey"))
+ sec := Sha256Bin(key)
sig, _ := secp256k1.Sign(hash, sec)
@@ -96,29 +97,33 @@ func (tx *Transaction) Signature() []byte {
}
func (tx *Transaction) PublicKey() []byte {
- hash := Sha256Bin(tx.MarshalRlp())
- sig := tx.Signature()
+ hash := Sha256Bin(tx.Hash())
+ sig := append(tx.r, tx.s...)
pubkey, _ := secp256k1.RecoverPubkey(hash, sig)
return pubkey
}
-func (tx *Transaction) Address() []byte {
- pubk := tx.PublicKey()
- // 1 is the marker 04
- key := pubk[1:65]
+func (tx *Transaction) Sender() []byte {
+ pubkey := tx.PublicKey()
- return Sha256Bin(key)[12:]
+ // 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) SetVRS() {
- // Add 27 so we get either 27 or 28 (for positive and negative)
- tx.v = uint32(tx.Signature()[64]) + 27
+func (tx *Transaction) Sign(privk []byte) {
+ sig := tx.Signature(privk)
- pubk := tx.PublicKey()[1:65]
- tx.r = pubk[:32]
- tx.s = pubk[32:64]
+ // 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 {
@@ -138,72 +143,23 @@ func (tx *Transaction) MarshalRlp() []byte {
}
func (tx *Transaction) UnmarshalRlp(data []byte) {
- t, _ := Decode(data,0)
- if slice, ok := t.([]interface{}); ok {
- if nonce, ok := slice[0].(uint8); ok {
- tx.nonce = string(nonce)
- }
-
- if recipient, ok := slice[1].([]byte); ok {
- tx.recipient = string(recipient)
- }
-
- // If only I knew of a better way.
- if value, ok := slice[2].(uint8); ok {
- tx.value = uint64(value)
- }
- if value, ok := slice[2].(uint16); ok {
- tx.value = uint64(value)
- }
- if value, ok := slice[2].(uint32); ok {
- tx.value = uint64(value)
- }
- if value, ok := slice[2].(uint64); ok {
- tx.value = uint64(value)
- }
- if fee, ok := slice[3].(uint8); ok {
- tx.fee = uint32(fee)
- }
- if fee, ok := slice[3].(uint16); ok {
- tx.fee = uint32(fee)
- }
- if fee, ok := slice[3].(uint32); ok {
- tx.fee = uint32(fee)
- }
- if fee, ok := slice[3].(uint64); ok {
- tx.fee = uint32(fee)
- }
-
- // Encode the data/instructions
- if data, ok := slice[4].([]interface{}); ok {
- tx.data = make([]string, len(data))
- for i, d := range data {
- if instr, ok := d.([]byte); ok {
- tx.data[i] = string(instr)
- }
- }
- }
-
- // vrs
- if v, ok := slice[5].(uint8); ok {
- tx.v = uint32(v)
- }
- if v, ok := slice[5].(uint16); ok {
- tx.v = uint32(v)
- }
- if v, ok := slice[5].(uint32); ok {
- tx.v = uint32(v)
- }
- if v, ok := slice[5].(uint64); ok {
- tx.v = uint32(v)
- }
- if r, ok := slice[6].([]byte); ok {
- tx.r = r
- }
- if s, ok := slice[7].([]byte); ok {
- tx.s = s
- }
+ 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() {