Running contracts fixed
This commit is contained in:
parent
c866fcc5b3
commit
24f2b2afc3
@ -46,6 +46,8 @@ type Block struct {
|
|||||||
// List of transactions and/or contracts
|
// List of transactions and/or contracts
|
||||||
transactions []*Transaction
|
transactions []*Transaction
|
||||||
TxSha []byte
|
TxSha []byte
|
||||||
|
|
||||||
|
contractStates map[string]*ethutil.Trie
|
||||||
}
|
}
|
||||||
|
|
||||||
// New block takes a raw encoded string
|
// New block takes a raw encoded string
|
||||||
@ -79,14 +81,15 @@ func CreateBlock(root interface{},
|
|||||||
|
|
||||||
block := &Block{
|
block := &Block{
|
||||||
// Slice of transactions to include in this block
|
// Slice of transactions to include in this block
|
||||||
transactions: txes,
|
transactions: txes,
|
||||||
PrevHash: prevHash,
|
PrevHash: prevHash,
|
||||||
Coinbase: base,
|
Coinbase: base,
|
||||||
Difficulty: Difficulty,
|
Difficulty: Difficulty,
|
||||||
Nonce: Nonce,
|
Nonce: Nonce,
|
||||||
Time: time.Now().Unix(),
|
Time: time.Now().Unix(),
|
||||||
Extra: extra,
|
Extra: extra,
|
||||||
UncleSha: EmptyShaList,
|
UncleSha: EmptyShaList,
|
||||||
|
contractStates: make(map[string]*ethutil.Trie),
|
||||||
}
|
}
|
||||||
block.SetTransactions(txes)
|
block.SetTransactions(txes)
|
||||||
block.SetUncles([]*Block{})
|
block.SetUncles([]*Block{})
|
||||||
@ -131,6 +134,13 @@ func (block *Block) GetContract(addr []byte) *Contract {
|
|||||||
contract := &Contract{}
|
contract := &Contract{}
|
||||||
contract.RlpDecode([]byte(data))
|
contract.RlpDecode([]byte(data))
|
||||||
|
|
||||||
|
cachedState := block.contractStates[string(addr)]
|
||||||
|
if cachedState != nil {
|
||||||
|
contract.state = cachedState
|
||||||
|
} else {
|
||||||
|
block.contractStates[string(addr)] = contract.state
|
||||||
|
}
|
||||||
|
|
||||||
return contract
|
return contract
|
||||||
}
|
}
|
||||||
func (block *Block) UpdateContract(addr []byte, contract *Contract) {
|
func (block *Block) UpdateContract(addr []byte, contract *Contract) {
|
||||||
@ -190,6 +200,25 @@ func (block *Block) BlockInfo() BlockInfo {
|
|||||||
return bi
|
return bi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sync the block's state and contract respectively
|
||||||
|
func (block *Block) Sync() {
|
||||||
|
// Sync all contracts currently in cache
|
||||||
|
for _, val := range block.contractStates {
|
||||||
|
val.Sync()
|
||||||
|
}
|
||||||
|
// Sync the block state itself
|
||||||
|
block.state.Sync()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (block *Block) Undo() {
|
||||||
|
// Sync all contracts currently in cache
|
||||||
|
for _, val := range block.contractStates {
|
||||||
|
val.Undo()
|
||||||
|
}
|
||||||
|
// Sync the block state itself
|
||||||
|
block.state.Undo()
|
||||||
|
}
|
||||||
|
|
||||||
func (block *Block) MakeContract(tx *Transaction) {
|
func (block *Block) MakeContract(tx *Transaction) {
|
||||||
// Create contract if there's no recipient
|
// Create contract if there's no recipient
|
||||||
if tx.IsContract() {
|
if tx.IsContract() {
|
||||||
@ -199,9 +228,14 @@ func (block *Block) MakeContract(tx *Transaction) {
|
|||||||
contract := NewContract(value, []byte(""))
|
contract := NewContract(value, []byte(""))
|
||||||
block.state.Update(string(addr), string(contract.RlpEncode()))
|
block.state.Update(string(addr), string(contract.RlpEncode()))
|
||||||
for i, val := range tx.Data {
|
for i, val := range tx.Data {
|
||||||
contract.state.Update(string(ethutil.NumberToBytes(uint64(i), 32)), val)
|
if len(val) > 0 {
|
||||||
|
bytNum := ethutil.BigToBytes(big.NewInt(int64(i)), 256)
|
||||||
|
contract.state.Update(string(bytNum), val)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
block.UpdateContract(addr, contract)
|
block.UpdateContract(addr, contract)
|
||||||
|
|
||||||
|
block.contractStates[string(addr)] = contract.state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,6 +322,7 @@ func (block *Block) RlpValueDecode(decoder *ethutil.Value) {
|
|||||||
block.Time = int64(header.Get(6).BigInt().Uint64())
|
block.Time = int64(header.Get(6).BigInt().Uint64())
|
||||||
block.Extra = header.Get(7).Str()
|
block.Extra = header.Get(7).Str()
|
||||||
block.Nonce = header.Get(8).Bytes()
|
block.Nonce = header.Get(8).Bytes()
|
||||||
|
block.contractStates = make(map[string]*ethutil.Trie)
|
||||||
|
|
||||||
// Tx list might be empty if this is an uncle. Uncles only have their
|
// Tx list might be empty if this is an uncle. Uncles only have their
|
||||||
// header set.
|
// header set.
|
||||||
|
@ -107,7 +107,7 @@ func (bm *BlockManager) ProcessBlock(block *Block) error {
|
|||||||
// we don't want to undo but since undo only happens on dirty
|
// we don't want to undo but since undo only happens on dirty
|
||||||
// nodes this won't happen because Commit would have been called
|
// nodes this won't happen because Commit would have been called
|
||||||
// before that.
|
// before that.
|
||||||
defer bm.bc.CurrentBlock.State().Undo()
|
defer bm.bc.CurrentBlock.Undo()
|
||||||
|
|
||||||
hash := block.Hash()
|
hash := block.Hash()
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ func (bm *BlockManager) ProcessBlock(block *Block) error {
|
|||||||
// Calculate the new total difficulty and sync back to the db
|
// Calculate the new total difficulty and sync back to the db
|
||||||
if bm.CalculateTD(block) {
|
if bm.CalculateTD(block) {
|
||||||
// Sync the current block's state to the database and cancelling out the deferred Undo
|
// Sync the current block's state to the database and cancelling out the deferred Undo
|
||||||
bm.bc.CurrentBlock.State().Sync()
|
bm.bc.CurrentBlock.Sync()
|
||||||
// Add the block to the chain
|
// Add the block to the chain
|
||||||
bm.bc.Add(block)
|
bm.bc.Add(block)
|
||||||
|
|
||||||
@ -280,11 +280,13 @@ func (bm *BlockManager) Stop() {
|
|||||||
|
|
||||||
func (bm *BlockManager) ProcessContract(tx *Transaction, block *Block) {
|
func (bm *BlockManager) ProcessContract(tx *Transaction, block *Block) {
|
||||||
// Recovering function in case the VM had any errors
|
// Recovering function in case the VM had any errors
|
||||||
defer func() {
|
/*
|
||||||
if r := recover(); r != nil {
|
defer func() {
|
||||||
fmt.Println("Recovered from VM execution with err =", r)
|
if r := recover(); r != nil {
|
||||||
}
|
fmt.Println("Recovered from VM execution with err =", r)
|
||||||
}()
|
}
|
||||||
|
}()
|
||||||
|
*/
|
||||||
|
|
||||||
// Process contract
|
// Process contract
|
||||||
bm.ProcContract(tx, block, func(opType OpType) bool {
|
bm.ProcContract(tx, block, func(opType OpType) bool {
|
||||||
@ -305,6 +307,7 @@ func (bm *BlockManager) ProcContract(tx *Transaction, block *Block, cb TxCallbac
|
|||||||
blockInfo := bm.bc.BlockInfo(block)
|
blockInfo := bm.bc.BlockInfo(block)
|
||||||
|
|
||||||
contract := block.GetContract(tx.Hash())
|
contract := block.GetContract(tx.Hash())
|
||||||
|
|
||||||
if contract == nil {
|
if contract == nil {
|
||||||
fmt.Println("Contract not found")
|
fmt.Println("Contract not found")
|
||||||
return
|
return
|
||||||
@ -313,7 +316,7 @@ func (bm *BlockManager) ProcContract(tx *Transaction, block *Block, cb TxCallbac
|
|||||||
Pow256 := ethutil.BigPow(2, 256)
|
Pow256 := ethutil.BigPow(2, 256)
|
||||||
|
|
||||||
if ethutil.Config.Debug {
|
if ethutil.Config.Debug {
|
||||||
fmt.Printf("# op arg\n")
|
fmt.Printf("# op\n")
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
for {
|
for {
|
||||||
@ -321,9 +324,11 @@ out:
|
|||||||
base := new(big.Int)
|
base := new(big.Int)
|
||||||
// XXX Should Instr return big int slice instead of string slice?
|
// XXX Should Instr return big int slice instead of string slice?
|
||||||
// Get the next instruction from the contract
|
// Get the next instruction from the contract
|
||||||
//op, _, _ := Instr(contract.state.Get(string(Encode(uint32(pc)))))
|
nb := ethutil.BigToBytes(big.NewInt(int64(pc)), 256)
|
||||||
nb := ethutil.NumberToBytes(uint64(pc), 32)
|
r := contract.State().Get(string(nb))
|
||||||
o, _, _ := ethutil.Instr(contract.State().Get(string(nb)))
|
v := ethutil.NewValueFromBytes([]byte(r))
|
||||||
|
//fmt.Printf("%x = %d, %v %x\n", r, len(r), v, nb)
|
||||||
|
o := v.Uint()
|
||||||
op := OpCode(o)
|
op := OpCode(o)
|
||||||
|
|
||||||
if !cb(0) {
|
if !cb(0) {
|
||||||
@ -575,7 +580,10 @@ out:
|
|||||||
case oSSTORE:
|
case oSSTORE:
|
||||||
// Store Y at index X
|
// Store Y at index X
|
||||||
x, y := bm.stack.Popn()
|
x, y := bm.stack.Popn()
|
||||||
contract.State().Update(x.String(), string(ethutil.Encode(y)))
|
idx := ethutil.BigToBytes(x, 256)
|
||||||
|
val := ethutil.NewValue(y)
|
||||||
|
//fmt.Printf("STORING VALUE: %v @ %v\n", val.BigInt(), ethutil.BigD(idx))
|
||||||
|
contract.State().Update(string(idx), string(val.Encode()))
|
||||||
case oJMP:
|
case oJMP:
|
||||||
x := int(bm.stack.Pop().Uint64())
|
x := int(bm.stack.Pop().Uint64())
|
||||||
// Set pc to x - 1 (minus one so the incrementing at the end won't effect it)
|
// Set pc to x - 1 (minus one so the incrementing at the end won't effect it)
|
||||||
@ -617,7 +625,10 @@ out:
|
|||||||
bm.TransactionPool.QueueTransaction(tx)
|
bm.TransactionPool.QueueTransaction(tx)
|
||||||
case oSUICIDE:
|
case oSUICIDE:
|
||||||
//addr := bm.stack.Pop()
|
//addr := bm.stack.Pop()
|
||||||
|
default:
|
||||||
|
fmt.Println("Invalid OPCODE", op)
|
||||||
}
|
}
|
||||||
|
//bm.stack.Print()
|
||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,75 +1,29 @@
|
|||||||
package ethchain
|
package ethchain
|
||||||
|
|
||||||
/*
|
|
||||||
import (
|
import (
|
||||||
_ "fmt"
|
_ "fmt"
|
||||||
|
"github.com/ethereum/eth-go/ethdb"
|
||||||
|
"github.com/ethereum/eth-go/ethutil"
|
||||||
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestVm(t *testing.T) {
|
func TestVm(t *testing.T) {
|
||||||
InitFees()
|
InitFees()
|
||||||
|
ethutil.ReadConfig("")
|
||||||
|
|
||||||
db, _ := NewMemDatabase()
|
db, _ := ethdb.NewMemDatabase()
|
||||||
Db = db
|
ethutil.Config.Db = db
|
||||||
|
bm := NewBlockManager(nil)
|
||||||
|
|
||||||
ctrct := NewTransaction("", 200000000, []string{
|
block := bm.bc.genesisBlock
|
||||||
"PUSH", "1a2f2e",
|
ctrct := NewTransaction(ContractAddr, big.NewInt(200000000), []string{
|
||||||
"PUSH", "hallo",
|
"PUSH",
|
||||||
"POP", // POP hallo
|
"1",
|
||||||
"PUSH", "3",
|
"PUSH",
|
||||||
"LOAD", // Load hallo back on the stack
|
"2",
|
||||||
|
|
||||||
"PUSH", "1",
|
|
||||||
"PUSH", "2",
|
|
||||||
"ADD",
|
|
||||||
|
|
||||||
"PUSH", "2",
|
|
||||||
"PUSH", "1",
|
|
||||||
"SUB",
|
|
||||||
|
|
||||||
"PUSH", "100000000000000000000000",
|
|
||||||
"PUSH", "10000000000000",
|
|
||||||
"SDIV",
|
|
||||||
|
|
||||||
"PUSH", "105",
|
|
||||||
"PUSH", "200",
|
|
||||||
"MOD",
|
|
||||||
|
|
||||||
"PUSH", "100000000000000000000000",
|
|
||||||
"PUSH", "10000000000000",
|
|
||||||
"SMOD",
|
|
||||||
|
|
||||||
"PUSH", "5",
|
|
||||||
"PUSH", "10",
|
|
||||||
"LT",
|
|
||||||
|
|
||||||
"PUSH", "5",
|
|
||||||
"PUSH", "5",
|
|
||||||
"LE",
|
|
||||||
|
|
||||||
"PUSH", "50",
|
|
||||||
"PUSH", "5",
|
|
||||||
"GT",
|
|
||||||
|
|
||||||
"PUSH", "5",
|
|
||||||
"PUSH", "5",
|
|
||||||
"GE",
|
|
||||||
|
|
||||||
"PUSH", "10",
|
|
||||||
"PUSH", "10",
|
|
||||||
"NOT",
|
|
||||||
|
|
||||||
"MYADDRESS",
|
|
||||||
"TXSENDER",
|
|
||||||
|
|
||||||
"STOP",
|
"STOP",
|
||||||
})
|
})
|
||||||
tx := NewTransaction("1e8a42ea8cce13", 100, []string{})
|
bm.ApplyTransactions(block, []*Transaction{ctrct})
|
||||||
|
|
||||||
block := CreateBlock("", 0, "", "c014ba53", 0, 0, "", []*Transaction{ctrct, tx})
|
|
||||||
db.Put(block.Hash(), block.RlpEncode())
|
|
||||||
|
|
||||||
bm := NewBlockManager()
|
|
||||||
bm.ProcessBlock(block)
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
@ -163,5 +163,12 @@ func (st *Stack) Push(d *big.Int) {
|
|||||||
st.data = append(st.data, d)
|
st.data = append(st.data, d)
|
||||||
}
|
}
|
||||||
func (st *Stack) Print() {
|
func (st *Stack) Print() {
|
||||||
fmt.Println(st.data)
|
fmt.Println("# val (STACK)")
|
||||||
|
if len(st.data) > 0 {
|
||||||
|
for i, val := range st.data {
|
||||||
|
fmt.Printf("%-3d %v\n", i, val)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println("-- empty --")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
package ethchain
|
package ethchain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"github.com/ethereum/eth-go/ethutil"
|
"github.com/ethereum/eth-go/ethutil"
|
||||||
"github.com/obscuren/secp256k1-go"
|
"github.com/obscuren/secp256k1-go"
|
||||||
"math/big"
|
"math/big"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ContractAddr = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
|
|
||||||
type Transaction struct {
|
type Transaction struct {
|
||||||
Nonce uint64
|
Nonce uint64
|
||||||
Recipient []byte
|
Recipient []byte
|
||||||
@ -65,7 +68,7 @@ func (tx *Transaction) Hash() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) IsContract() bool {
|
func (tx *Transaction) IsContract() bool {
|
||||||
return len(tx.Recipient) == 0
|
return bytes.Compare(tx.Recipient, ContractAddr) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) Signature(key []byte) []byte {
|
func (tx *Transaction) Signature(key []byte) []byte {
|
||||||
|
@ -2,8 +2,6 @@ package ethchain
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
|
||||||
"github.com/ethereum/eth-go/ethutil"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -42,13 +40,15 @@ func TestAddressRetrieval2(t *testing.T) {
|
|||||||
tx.Sign(key)
|
tx.Sign(key)
|
||||||
//data, _ := hex.DecodeString("f85d8094944400f4b88ac9589a0f17ed4671da26bddb668b8203e8c01ca0363b2a410de00bc89be40f468d16e70e543b72191fbd8a684a7c5bef51dc451fa02d8ecf40b68f9c64ed623f6ee24c9c878943b812e1e76bd73ccb2bfef65579e7")
|
//data, _ := hex.DecodeString("f85d8094944400f4b88ac9589a0f17ed4671da26bddb668b8203e8c01ca0363b2a410de00bc89be40f468d16e70e543b72191fbd8a684a7c5bef51dc451fa02d8ecf40b68f9c64ed623f6ee24c9c878943b812e1e76bd73ccb2bfef65579e7")
|
||||||
//tx := NewTransactionFromData(data)
|
//tx := NewTransactionFromData(data)
|
||||||
fmt.Println(tx.RlpValue())
|
/*
|
||||||
|
fmt.Println(tx.RlpValue())
|
||||||
|
|
||||||
fmt.Printf("rlp %x\n", tx.RlpEncode())
|
fmt.Printf("rlp %x\n", tx.RlpEncode())
|
||||||
fmt.Printf("sha rlp %x\n", tx.Hash())
|
fmt.Printf("sha rlp %x\n", tx.Hash())
|
||||||
|
|
||||||
//tx.Sign(key)
|
//tx.Sign(key)
|
||||||
|
|
||||||
fmt.Printf("hex tx key %x\n", tx.PublicKey())
|
fmt.Printf("hex tx key %x\n", tx.PublicKey())
|
||||||
fmt.Printf("seder %x\n", tx.Sender())
|
fmt.Printf("seder %x\n", tx.Sender())
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ func (s *Ethereum) Start() {
|
|||||||
if ethutil.Config.Seed {
|
if ethutil.Config.Seed {
|
||||||
log.Println("Seeding")
|
log.Println("Seeding")
|
||||||
// Testnet seed bootstrapping
|
// Testnet seed bootstrapping
|
||||||
resp, err := http.Get("http://www.ethereum.org/servers.poc2.txt")
|
resp, err := http.Get("http://www.ethereum.org/servers.poc3.txt")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Fetching seed failed:", err)
|
log.Println("Fetching seed failed:", err)
|
||||||
return
|
return
|
||||||
|
@ -35,3 +35,9 @@ func BigD(data []byte) *big.Int {
|
|||||||
|
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BigToBytes(num *big.Int, base int) []byte {
|
||||||
|
ret := make([]byte, base/8)
|
||||||
|
|
||||||
|
return append(ret[:len(ret)-len(num.Bytes())], num.Bytes()...)
|
||||||
|
}
|
||||||
|
@ -34,12 +34,14 @@ func ReadConfig(base string) *config {
|
|||||||
usr, _ := user.Current()
|
usr, _ := user.Current()
|
||||||
path := path.Join(usr.HomeDir, base)
|
path := path.Join(usr.HomeDir, base)
|
||||||
|
|
||||||
//Check if the logging directory already exists, create it if not
|
if len(base) > 0 {
|
||||||
_, err := os.Stat(path)
|
//Check if the logging directory already exists, create it if not
|
||||||
if err != nil {
|
_, err := os.Stat(path)
|
||||||
if os.IsNotExist(err) {
|
if err != nil {
|
||||||
log.Printf("Debug logging directory %s doesn't exist, creating it", path)
|
if os.IsNotExist(err) {
|
||||||
os.Mkdir(path, 0777)
|
log.Printf("Debug logging directory %s doesn't exist, creating it", path)
|
||||||
|
os.Mkdir(path, 0777)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +119,10 @@ func (t *Trie) Undo() {
|
|||||||
t.Root = t.prevRoot
|
t.Root = t.prevRoot
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Trie) Cache() *Cache {
|
||||||
|
return t.cache
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Public (query) interface functions
|
* Public (query) interface functions
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user