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
|
||||
transactions []*Transaction
|
||||
TxSha []byte
|
||||
|
||||
contractStates map[string]*ethutil.Trie
|
||||
}
|
||||
|
||||
// New block takes a raw encoded string
|
||||
@ -87,6 +89,7 @@ func CreateBlock(root interface{},
|
||||
Time: time.Now().Unix(),
|
||||
Extra: extra,
|
||||
UncleSha: EmptyShaList,
|
||||
contractStates: make(map[string]*ethutil.Trie),
|
||||
}
|
||||
block.SetTransactions(txes)
|
||||
block.SetUncles([]*Block{})
|
||||
@ -131,6 +134,13 @@ func (block *Block) GetContract(addr []byte) *Contract {
|
||||
contract := &Contract{}
|
||||
contract.RlpDecode([]byte(data))
|
||||
|
||||
cachedState := block.contractStates[string(addr)]
|
||||
if cachedState != nil {
|
||||
contract.state = cachedState
|
||||
} else {
|
||||
block.contractStates[string(addr)] = contract.state
|
||||
}
|
||||
|
||||
return contract
|
||||
}
|
||||
func (block *Block) UpdateContract(addr []byte, contract *Contract) {
|
||||
@ -190,6 +200,25 @@ func (block *Block) BlockInfo() BlockInfo {
|
||||
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) {
|
||||
// Create contract if there's no recipient
|
||||
if tx.IsContract() {
|
||||
@ -199,9 +228,14 @@ func (block *Block) MakeContract(tx *Transaction) {
|
||||
contract := NewContract(value, []byte(""))
|
||||
block.state.Update(string(addr), string(contract.RlpEncode()))
|
||||
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.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.Extra = header.Get(7).Str()
|
||||
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
|
||||
// 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
|
||||
// nodes this won't happen because Commit would have been called
|
||||
// before that.
|
||||
defer bm.bc.CurrentBlock.State().Undo()
|
||||
defer bm.bc.CurrentBlock.Undo()
|
||||
|
||||
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
|
||||
if bm.CalculateTD(block) {
|
||||
// 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
|
||||
bm.bc.Add(block)
|
||||
|
||||
@ -280,11 +280,13 @@ func (bm *BlockManager) Stop() {
|
||||
|
||||
func (bm *BlockManager) ProcessContract(tx *Transaction, block *Block) {
|
||||
// Recovering function in case the VM had any errors
|
||||
/*
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println("Recovered from VM execution with err =", r)
|
||||
}
|
||||
}()
|
||||
*/
|
||||
|
||||
// Process contract
|
||||
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)
|
||||
|
||||
contract := block.GetContract(tx.Hash())
|
||||
|
||||
if contract == nil {
|
||||
fmt.Println("Contract not found")
|
||||
return
|
||||
@ -313,7 +316,7 @@ func (bm *BlockManager) ProcContract(tx *Transaction, block *Block, cb TxCallbac
|
||||
Pow256 := ethutil.BigPow(2, 256)
|
||||
|
||||
if ethutil.Config.Debug {
|
||||
fmt.Printf("# op arg\n")
|
||||
fmt.Printf("# op\n")
|
||||
}
|
||||
out:
|
||||
for {
|
||||
@ -321,9 +324,11 @@ out:
|
||||
base := new(big.Int)
|
||||
// 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)))))
|
||||
nb := ethutil.NumberToBytes(uint64(pc), 32)
|
||||
o, _, _ := ethutil.Instr(contract.State().Get(string(nb)))
|
||||
nb := ethutil.BigToBytes(big.NewInt(int64(pc)), 256)
|
||||
r := 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)
|
||||
|
||||
if !cb(0) {
|
||||
@ -575,7 +580,10 @@ out:
|
||||
case oSSTORE:
|
||||
// Store Y at index X
|
||||
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:
|
||||
x := int(bm.stack.Pop().Uint64())
|
||||
// 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)
|
||||
case oSUICIDE:
|
||||
//addr := bm.stack.Pop()
|
||||
default:
|
||||
fmt.Println("Invalid OPCODE", op)
|
||||
}
|
||||
//bm.stack.Print()
|
||||
pc++
|
||||
}
|
||||
}
|
||||
|
@ -1,75 +1,29 @@
|
||||
package ethchain
|
||||
|
||||
/*
|
||||
import (
|
||||
_ "fmt"
|
||||
"github.com/ethereum/eth-go/ethdb"
|
||||
"github.com/ethereum/eth-go/ethutil"
|
||||
"math/big"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestVm(t *testing.T) {
|
||||
InitFees()
|
||||
ethutil.ReadConfig("")
|
||||
|
||||
db, _ := NewMemDatabase()
|
||||
Db = db
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
ethutil.Config.Db = db
|
||||
bm := NewBlockManager(nil)
|
||||
|
||||
ctrct := NewTransaction("", 200000000, []string{
|
||||
"PUSH", "1a2f2e",
|
||||
"PUSH", "hallo",
|
||||
"POP", // POP hallo
|
||||
"PUSH", "3",
|
||||
"LOAD", // Load hallo back on the stack
|
||||
|
||||
"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",
|
||||
block := bm.bc.genesisBlock
|
||||
ctrct := NewTransaction(ContractAddr, big.NewInt(200000000), []string{
|
||||
"PUSH",
|
||||
"1",
|
||||
"PUSH",
|
||||
"2",
|
||||
|
||||
"STOP",
|
||||
})
|
||||
tx := NewTransaction("1e8a42ea8cce13", 100, []string{})
|
||||
|
||||
block := CreateBlock("", 0, "", "c014ba53", 0, 0, "", []*Transaction{ctrct, tx})
|
||||
db.Put(block.Hash(), block.RlpEncode())
|
||||
|
||||
bm := NewBlockManager()
|
||||
bm.ProcessBlock(block)
|
||||
bm.ApplyTransactions(block, []*Transaction{ctrct})
|
||||
}
|
||||
*/
|
||||
|
@ -163,5 +163,12 @@ func (st *Stack) Push(d *big.Int) {
|
||||
st.data = append(st.data, d)
|
||||
}
|
||||
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
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/ethereum/eth-go/ethutil"
|
||||
"github.com/obscuren/secp256k1-go"
|
||||
"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 {
|
||||
Nonce uint64
|
||||
Recipient []byte
|
||||
@ -65,7 +68,7 @@ func (tx *Transaction) Hash() []byte {
|
||||
}
|
||||
|
||||
func (tx *Transaction) IsContract() bool {
|
||||
return len(tx.Recipient) == 0
|
||||
return bytes.Compare(tx.Recipient, ContractAddr) == 0
|
||||
}
|
||||
|
||||
func (tx *Transaction) Signature(key []byte) []byte {
|
||||
|
@ -2,8 +2,6 @@ package ethchain
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/ethereum/eth-go/ethutil"
|
||||
"math/big"
|
||||
"testing"
|
||||
)
|
||||
@ -42,6 +40,7 @@ func TestAddressRetrieval2(t *testing.T) {
|
||||
tx.Sign(key)
|
||||
//data, _ := hex.DecodeString("f85d8094944400f4b88ac9589a0f17ed4671da26bddb668b8203e8c01ca0363b2a410de00bc89be40f468d16e70e543b72191fbd8a684a7c5bef51dc451fa02d8ecf40b68f9c64ed623f6ee24c9c878943b812e1e76bd73ccb2bfef65579e7")
|
||||
//tx := NewTransactionFromData(data)
|
||||
/*
|
||||
fmt.Println(tx.RlpValue())
|
||||
|
||||
fmt.Printf("rlp %x\n", tx.RlpEncode())
|
||||
@ -51,4 +50,5 @@ func TestAddressRetrieval2(t *testing.T) {
|
||||
|
||||
fmt.Printf("hex tx key %x\n", tx.PublicKey())
|
||||
fmt.Printf("seder %x\n", tx.Sender())
|
||||
*/
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ func (s *Ethereum) Start() {
|
||||
if ethutil.Config.Seed {
|
||||
log.Println("Seeding")
|
||||
// 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 {
|
||||
log.Println("Fetching seed failed:", err)
|
||||
return
|
||||
|
@ -35,3 +35,9 @@ func BigD(data []byte) *big.Int {
|
||||
|
||||
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,6 +34,7 @@ func ReadConfig(base string) *config {
|
||||
usr, _ := user.Current()
|
||||
path := path.Join(usr.HomeDir, base)
|
||||
|
||||
if len(base) > 0 {
|
||||
//Check if the logging directory already exists, create it if not
|
||||
_, err := os.Stat(path)
|
||||
if err != nil {
|
||||
@ -42,6 +43,7 @@ func ReadConfig(base string) *config {
|
||||
os.Mkdir(path, 0777)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Config = &config{ExecPath: path, Debug: true, Ver: "0.2.3"}
|
||||
Config.Log = NewLogger(LogFile|LogStd, 0)
|
||||
|
@ -119,6 +119,10 @@ func (t *Trie) Undo() {
|
||||
t.Root = t.prevRoot
|
||||
}
|
||||
|
||||
func (t *Trie) Cache() *Cache {
|
||||
return t.cache
|
||||
}
|
||||
|
||||
/*
|
||||
* Public (query) interface functions
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user