forked from cerc-io/plugeth
Updated marshalling
This commit is contained in:
parent
9f133a92d0
commit
0929f59ec2
89
block.go
89
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()))
|
block.state.Update(string(addr), string(contract.MarshalRlp()))
|
||||||
for i, val := range tx.data {
|
for i, val := range tx.data {
|
||||||
contract.state.Update(string(NumberToBytes(uint64(i), 32)), val)
|
contract.state.Update(string(NumberToBytes(uint64(i), 32)), val)
|
||||||
//contract.state.Update(string(Encode(uint32(i))), val)
|
|
||||||
}
|
}
|
||||||
block.UpdateContract(addr, contract)
|
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 we can't pay the fee return
|
||||||
if contract == nil || contract.amount < fee {
|
if contract == nil || contract.amount < fee {
|
||||||
fmt.Println("Contract has insufficient funds", contract.amount, fee)
|
fmt.Println("Contract has insufficient funds", contract.amount, fee)
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ func (block *Block) PayFee(addr []byte, fee uint64) bool {
|
|||||||
block.state.Update(string(addr), string(contract.MarshalRlp()))
|
block.state.Update(string(addr), string(contract.MarshalRlp()))
|
||||||
|
|
||||||
data := block.state.Get(string(block.coinbase))
|
data := block.state.Get(string(block.coinbase))
|
||||||
println(data)
|
|
||||||
// Get the ether (coinbase) and add the fee (gief fee to miner)
|
// Get the ether (coinbase) and add the fee (gief fee to miner)
|
||||||
ether := NewEtherFromData([]byte(data))
|
ether := NewEtherFromData([]byte(data))
|
||||||
ether.amount += fee
|
ether.amount += fee
|
||||||
@ -159,75 +159,24 @@ func (block *Block) MarshalRlp() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (block *Block) UnmarshalRlp(data []byte) {
|
func (block *Block) UnmarshalRlp(data []byte) {
|
||||||
t, _ := Decode(data,0)
|
decoder := NewRlpDecoder(data)
|
||||||
|
|
||||||
// interface slice assertion
|
header := decoder.Get(0)
|
||||||
if slice, ok := t.([]interface{}); ok {
|
block.number = uint32(header.Get(0).AsUint())
|
||||||
// interface slice assertion
|
block.prevHash = header.Get(1).AsString()
|
||||||
if header, ok := slice[0].([]interface{}); ok {
|
// sha of uncles is header[2]
|
||||||
if number, ok := header[0].(uint8); ok {
|
block.coinbase = header.Get(3).AsString()
|
||||||
block.number = uint32(number)
|
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()
|
||||||
|
|
||||||
if prevHash, ok := header[1].([]uint8); ok {
|
txes := decoder.Get(1)
|
||||||
block.prevHash = string(prevHash)
|
block.transactions = make([]*Transaction, txes.Length())
|
||||||
}
|
for i := 0; i < txes.Length(); i++ {
|
||||||
|
tx := &Transaction{}
|
||||||
// sha of uncles is header[2]
|
tx.UnmarshalRlp(txes.Get(i).AsBytes())
|
||||||
|
block.transactions[i] = tx
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
24
contract.go
24
contract.go
@ -22,27 +22,11 @@ func (c *Contract) MarshalRlp() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Contract) UnmarshalRlp(data []byte) {
|
func (c *Contract) UnmarshalRlp(data []byte) {
|
||||||
t, _ := Decode(data, 0)
|
decoder := NewRlpDecoder(data)
|
||||||
|
|
||||||
if slice, ok := t.([]interface{}); ok {
|
c.t = uint32(decoder.Get(0).AsUint())
|
||||||
if t, ok := slice[0].(uint8); ok {
|
c.amount = decoder.Get(1).AsUint()
|
||||||
c.t = uint32(t)
|
c.state = NewTrie(Db, decoder.Get(2).AsString())
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Ether struct {
|
type Ether struct {
|
||||||
|
@ -32,5 +32,3 @@ var GenisisHeader = []interface{}{
|
|||||||
}
|
}
|
||||||
|
|
||||||
var Genesis = []interface{}{ GenisisHeader, []interface{}{}, []interface{}{} }
|
var Genesis = []interface{}{ GenisisHeader, []interface{}{}, []interface{}{} }
|
||||||
|
|
||||||
var GenisisBlock = NewBlock( Encode(Genesis) )
|
|
||||||
|
105
rlp.go
105
rlp.go
@ -4,8 +4,110 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"bytes"
|
"bytes"
|
||||||
"math"
|
"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 {
|
func BinaryLength(n uint64) uint64 {
|
||||||
if n == 0 { return 0 }
|
if n == 0 { return 0 }
|
||||||
|
|
||||||
@ -122,6 +224,9 @@ func Encode(object interface{}) []byte {
|
|||||||
buff.WriteString(string(len(b2) + 55) + b2 + b)
|
buff.WriteString(string(len(b2) + 55) + b2 + b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case *big.Int:
|
||||||
|
buff.Write(Encode(t.String()))
|
||||||
|
|
||||||
case string:
|
case string:
|
||||||
if len(t) < 56 {
|
if len(t) < 56 {
|
||||||
buff.WriteString(string(len(t) + 64) + t)
|
buff.WriteString(string(len(t) + 64) + t)
|
||||||
|
116
transaction.go
116
transaction.go
@ -2,7 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
_"fmt"
|
"fmt"
|
||||||
"github.com/obscuren/secp256k1-go"
|
"github.com/obscuren/secp256k1-go"
|
||||||
_"encoding/hex"
|
_"encoding/hex"
|
||||||
_"crypto/sha256"
|
_"crypto/sha256"
|
||||||
@ -64,7 +64,8 @@ func NewTransaction(to string, value uint64, data []string) *Transaction {
|
|||||||
tx.data[i] = instr
|
tx.data[i] = instr
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.SetVRS()
|
tx.Sign([]byte("privkey"))
|
||||||
|
tx.Sender()
|
||||||
|
|
||||||
|
|
||||||
return &tx
|
return &tx
|
||||||
@ -86,9 +87,9 @@ func (tx *Transaction) IsContract() bool {
|
|||||||
return tx.recipient == ""
|
return tx.recipient == ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) Signature() []byte {
|
func (tx *Transaction) Signature(key []byte) []byte {
|
||||||
hash := tx.Hash()
|
hash := tx.Hash()
|
||||||
sec := Sha256Bin([]byte("myprivkey"))
|
sec := Sha256Bin(key)
|
||||||
|
|
||||||
sig, _ := secp256k1.Sign(hash, sec)
|
sig, _ := secp256k1.Sign(hash, sec)
|
||||||
|
|
||||||
@ -96,29 +97,33 @@ func (tx *Transaction) Signature() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) PublicKey() []byte {
|
func (tx *Transaction) PublicKey() []byte {
|
||||||
hash := Sha256Bin(tx.MarshalRlp())
|
hash := Sha256Bin(tx.Hash())
|
||||||
sig := tx.Signature()
|
sig := append(tx.r, tx.s...)
|
||||||
|
|
||||||
pubkey, _ := secp256k1.RecoverPubkey(hash, sig)
|
pubkey, _ := secp256k1.RecoverPubkey(hash, sig)
|
||||||
|
|
||||||
return pubkey
|
return pubkey
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) Address() []byte {
|
func (tx *Transaction) Sender() []byte {
|
||||||
pubk := tx.PublicKey()
|
pubkey := tx.PublicKey()
|
||||||
// 1 is the marker 04
|
|
||||||
key := pubk[1:65]
|
|
||||||
|
|
||||||
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() {
|
func (tx *Transaction) Sign(privk []byte) {
|
||||||
// Add 27 so we get either 27 or 28 (for positive and negative)
|
sig := tx.Signature(privk)
|
||||||
tx.v = uint32(tx.Signature()[64]) + 27
|
|
||||||
|
|
||||||
pubk := tx.PublicKey()[1:65]
|
// Add 27 so we get either 27 or 28 (for positive and negative)
|
||||||
tx.r = pubk[:32]
|
tx.v = uint32(sig[64]) + 27
|
||||||
tx.s = pubk[32:64]
|
tx.r = sig[:32]
|
||||||
|
tx.s = sig[32:65]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) MarshalRlp() []byte {
|
func (tx *Transaction) MarshalRlp() []byte {
|
||||||
@ -138,72 +143,23 @@ func (tx *Transaction) MarshalRlp() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) UnmarshalRlp(data []byte) {
|
func (tx *Transaction) UnmarshalRlp(data []byte) {
|
||||||
t, _ := Decode(data,0)
|
decoder := NewRlpDecoder(data)
|
||||||
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.nonce = decoder.Get(0).AsString()
|
||||||
tx.recipient = string(recipient)
|
tx.recipient = decoder.Get(0).AsString()
|
||||||
}
|
tx.value = decoder.Get(2).AsUint()
|
||||||
|
tx.fee = uint32(decoder.Get(3).AsUint())
|
||||||
|
|
||||||
// If only I knew of a better way.
|
d := decoder.Get(4)
|
||||||
if value, ok := slice[2].(uint8); ok {
|
tx.data = make([]string, d.Length())
|
||||||
tx.value = uint64(value)
|
fmt.Println(d.Get(0))
|
||||||
}
|
for i := 0; i < d.Length(); i++ {
|
||||||
if value, ok := slice[2].(uint16); ok {
|
tx.data[i] = d.Get(i).AsString()
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tx.v = uint32(decoder.Get(5).AsUint())
|
||||||
|
tx.r = decoder.Get(6).AsBytes()
|
||||||
|
tx.s = decoder.Get(7).AsBytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitFees() {
|
func InitFees() {
|
||||||
|
Loading…
Reference in New Issue
Block a user