Browse Source

fixes from review with jae

pull/52/head
Ethan Buchman 10 years ago
parent
commit
a1c5e32d76
13 changed files with 174 additions and 175 deletions
  1. +6
    -0
      account/account.go
  2. +1
    -0
      consensus/state.go
  3. +88
    -83
      rpc/handlers.go
  4. +2
    -3
      rpc/http_server.go
  5. +14
    -18
      rpc/test/client_ws_test.go
  6. +8
    -6
      rpc/test/helpers.go
  7. +12
    -17
      rpc/test/tests.go
  8. +6
    -13
      rpc/test/ws_helpers.go
  9. +2
    -4
      state/block_cache.go
  10. +5
    -14
      state/execution.go
  11. +27
    -0
      types/events.go
  12. +0
    -8
      vm/types.go
  13. +3
    -9
      vm/vm.go

+ 6
- 0
account/account.go View File

@ -6,6 +6,7 @@ import (
"io"
"github.com/tendermint/tendermint/binary"
"github.com/tendermint/tendermint/merkle"
)
// Signable is an interface for all signable things.
@ -24,6 +25,11 @@ func SignBytes(o Signable) []byte {
return buf.Bytes()
}
// HashSignBytes is a convenience method for getting the hash of the bytes of a signable
func HashSignBytes(o Signable) []byte {
return merkle.HashFromBinary(SignBytes(o))
}
//-----------------------------------------------------------------------------
// Account resides in the application state, and is mutated by transactions


+ 1
- 0
consensus/state.go View File

@ -445,6 +445,7 @@ ACTION_LOOP:
// cs.Step is at RoundStepNewHeight or RoundStepNewRound.
newBlock := cs.blockStore.LoadBlock(cs.state.LastBlockHeight)
cs.evsw.FireEvent(types.EventStringNewBlock(), newBlock)
// TODO: go fire events from event cache
scheduleNextAction()
continue ACTION_LOOP
} else {


+ 88
- 83
rpc/handlers.go View File

@ -10,6 +10,7 @@ import (
"io/ioutil"
"net/http"
"reflect"
"sync/atomic"
"time"
)
@ -25,8 +26,8 @@ func RegisterRPCFuncs(mux *http.ServeMux, funcMap map[string]*RPCFunc) {
func RegisterEventsHandler(mux *http.ServeMux, evsw *events.EventSwitch) {
// websocket endpoint
w := NewWebsocketManager(evsw)
mux.HandleFunc("/events", w.websocketHandler) // websocket.Handler(w.eventsHandler))
wm := NewWebsocketManager(evsw)
mux.HandleFunc("/events", wm.websocketHandler) // websocket.Handler(w.eventsHandler))
}
//-------------------------------------
@ -193,7 +194,7 @@ func _jsonStringToArg(ty reflect.Type, arg string) (reflect.Value, error) {
const (
WSConnectionReaperSeconds = 5
MaxFailedSendsSeconds = 10
MaxFailedSends = 10
WriteChanBufferSize = 10
)
@ -214,103 +215,76 @@ type WSResponse struct {
// contains the listeners id
type Connection struct {
id string
wsCon *websocket.Conn
wsConn *websocket.Conn
writeChan chan WSResponse
quitChan chan struct{}
failedSends uint
started uint32
stopped uint32
evsw *events.EventSwitch
}
// new websocket connection wrapper
func NewConnection(con *websocket.Conn) *Connection {
func NewConnection(wsConn *websocket.Conn) *Connection {
return &Connection{
id: con.RemoteAddr().String(),
wsCon: con,
id: wsConn.RemoteAddr().String(),
wsConn: wsConn,
writeChan: make(chan WSResponse, WriteChanBufferSize), // buffered. we keep track when its full
}
}
// close the connection
func (c *Connection) Close() {
c.wsCon.Close()
close(c.writeChan)
close(c.quitChan)
}
// start the connection and hand her the event switch
func (con *Connection) Start(evsw *events.EventSwitch) {
if atomic.CompareAndSwapUint32(&con.started, 0, 1) {
con.evsw = evsw
// main manager for all websocket connections
// holds the event switch
type WebsocketManager struct {
websocket.Upgrader
ew *events.EventSwitch
cons map[string]*Connection
}
func NewWebsocketManager(ew *events.EventSwitch) *WebsocketManager {
return &WebsocketManager{
ew: ew,
cons: make(map[string]*Connection),
Upgrader: websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
CheckOrigin: func(r *http.Request) bool {
// TODO
return true
},
},
// read subscriptions/unsubscriptions to events
go con.read()
// write responses
con.write()
}
}
func (wm *WebsocketManager) websocketHandler(w http.ResponseWriter, r *http.Request) {
conn, err := wm.Upgrade(w, r, nil)
if err != nil {
// TODO
log.Error("Failed to upgrade to websocket connection", "error", err)
return
// close the connection
func (con *Connection) Stop() {
if atomic.CompareAndSwapUint32(&con.stopped, 0, 1) {
con.wsConn.Close()
close(con.writeChan)
}
wm.handleWebsocket(conn)
}
func (w *WebsocketManager) handleWebsocket(con *websocket.Conn) {
// register connection
c := NewConnection(con)
w.cons[c.id] = c
log.Info("New websocket connection", "origin", c.id)
// read subscriptions/unsubscriptions to events
go w.read(c)
// write responses
w.write(c)
}
// read from the socket and subscribe to or unsubscribe from events
func (w *WebsocketManager) read(con *Connection) {
func (con *Connection) read() {
reaper := time.Tick(time.Second * WSConnectionReaperSeconds)
for {
select {
case <-reaper:
if con.failedSends > MaxFailedSendsSeconds {
if con.failedSends > MaxFailedSends {
// sending has failed too many times.
// kill the connection
con.quitChan <- struct{}{}
con.Stop()
return
}
default:
var in []byte
_, in, err := con.wsCon.ReadMessage()
_, in, err := con.wsConn.ReadMessage()
if err != nil {
// an error reading the connection,
// so kill the connection
con.quitChan <- struct{}{}
// kill the connection
con.Stop()
return
}
var req WSRequest
err = json.Unmarshal(in, &req)
if err != nil {
errStr := fmt.Sprintf("Error unmarshaling data: %s", err.Error())
con.writeChan <- WSResponse{Error: errStr}
continue
}
switch req.Type {
case "subscribe":
log.Info("New event subscription", "con id", con.id, "event", req.Event)
w.ew.AddListenerForEvent(con.id, req.Event, func(msg interface{}) {
con.evsw.AddListenerForEvent(con.id, req.Event, func(msg interface{}) {
resp := WSResponse{
Event: req.Event,
Data: msg,
@ -328,9 +302,9 @@ func (w *WebsocketManager) read(con *Connection) {
})
case "unsubscribe":
if req.Event != "" {
w.ew.RemoveListenerForEvent(req.Event, con.id)
con.evsw.RemoveListenerForEvent(req.Event, con.id)
} else {
w.ew.RemoveListener(con.id)
con.evsw.RemoveListener(con.id)
}
default:
con.writeChan <- WSResponse{Error: "Unknown request type: " + req.Type}
@ -340,33 +314,64 @@ func (w *WebsocketManager) read(con *Connection) {
}
}
// receives on a write channel and writes out to the socket
func (w *WebsocketManager) write(con *Connection) {
// receives on a write channel and writes out on the socket
func (con *Connection) write() {
n, err := new(int64), new(error)
for {
select {
case msg := <-con.writeChan:
buf := new(bytes.Buffer)
binary.WriteJSON(msg, buf, n, err)
if *err != nil {
log.Error("Failed to write JSON WSResponse", "error", err)
} else {
//websocket.Message.Send(con.wsCon, buf.Bytes())
if err := con.wsCon.WriteMessage(websocket.TextMessage, buf.Bytes()); err != nil {
log.Error("Failed to write response on websocket", "error", err)
}
}
case <-con.quitChan:
w.closeConn(con)
msg, more := <-con.writeChan
if !more {
// the channel was closed, so ensure
// connection is stopped and return
con.Stop()
return
}
buf := new(bytes.Buffer)
binary.WriteJSON(msg, buf, n, err)
if *err != nil {
log.Error("Failed to write JSON WSResponse", "error", err)
} else {
if err := con.wsConn.WriteMessage(websocket.TextMessage, buf.Bytes()); err != nil {
log.Error("Failed to write response on websocket", "error", err)
con.Stop()
return
}
}
}
}
// close a connection and delete from manager
func (w *WebsocketManager) closeConn(con *Connection) {
con.Close()
delete(w.cons, con.id)
// main manager for all websocket connections
// holds the event switch
type WebsocketManager struct {
websocket.Upgrader
evsw *events.EventSwitch
}
func NewWebsocketManager(evsw *events.EventSwitch) *WebsocketManager {
return &WebsocketManager{
evsw: evsw,
Upgrader: websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
CheckOrigin: func(r *http.Request) bool {
// TODO
return true
},
},
}
}
func (wm *WebsocketManager) websocketHandler(w http.ResponseWriter, r *http.Request) {
wsConn, err := wm.Upgrade(w, r, nil)
if err != nil {
// TODO - return http error
log.Error("Failed to upgrade to websocket connection", "error", err)
return
}
// register connection
con := NewConnection(wsConn)
log.Info("New websocket connection", "origin", con.id)
con.Start(wm.evsw)
}
// rpc.websocket


+ 2
- 3
rpc/http_server.go View File

@ -53,7 +53,7 @@ func WriteRPCResponse(w http.ResponseWriter, res RPCResponse) {
func RecoverAndLogHandler(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Wrap the ResponseWriter to remember the status
rww := &ResponseWriterWrapper{-1, w, w.(http.Hijacker)}
rww := &ResponseWriterWrapper{-1, w}
begin := time.Now()
// Common headers
@ -100,7 +100,6 @@ func RecoverAndLogHandler(handler http.Handler) http.Handler {
type ResponseWriterWrapper struct {
Status int
http.ResponseWriter
hj http.Hijacker // necessary for websocket upgrades
}
func (w *ResponseWriterWrapper) WriteHeader(status int) {
@ -110,7 +109,7 @@ func (w *ResponseWriterWrapper) WriteHeader(status int) {
// implements http.Hijacker
func (w *ResponseWriterWrapper) Hijack() (net.Conn, *bufio.ReadWriter, error) {
return w.hj.Hijack()
return w.ResponseWriter.(http.Hijacker).Hijack()
}
// Stick it as a deferred statement in gouroutines to prevent the program from crashing.


+ 14
- 18
rpc/test/client_ws_test.go View File

@ -1,7 +1,6 @@
package rpc
import (
"encoding/hex"
"encoding/json"
"fmt"
"github.com/gorilla/websocket"
@ -172,7 +171,7 @@ func TestWSSend(t *testing.T) {
amt := uint64(100)
con := newWSCon(t)
eidInput := types.EventStringAccInput(byteAddr)
eidInput := types.EventStringAccInput(userByteAddr)
eidOutput := types.EventStringAccOutput(toAddr)
subscribe(t, con, eidInput)
subscribe(t, con, eidOutput)
@ -182,7 +181,7 @@ func TestWSSend(t *testing.T) {
con.Close()
}()
waitForEvent(t, con, eidInput, true, func() {
broadcastTx(t, "JSONRPC", byteAddr, toAddr, nil, byteKey, amt, 0, 0)
broadcastTx(t, "JSONRPC", userByteAddr, toAddr, nil, userBytePriv, amt, 0, 0)
}, unmarshalValidateSend(amt, toAddr))
waitForEvent(t, con, eidOutput, true, func() {}, unmarshalValidateSend(amt, toAddr))
}
@ -190,7 +189,7 @@ func TestWSSend(t *testing.T) {
// ensure events are only fired once for a given transaction
func TestWSDoubleFire(t *testing.T) {
con := newWSCon(t)
eid := types.EventStringAccInput(byteAddr)
eid := types.EventStringAccInput(userByteAddr)
subscribe(t, con, eid)
defer func() {
unsubscribe(t, con, eid)
@ -200,7 +199,7 @@ func TestWSDoubleFire(t *testing.T) {
toAddr := []byte{20, 143, 25, 63, 16, 177, 83, 29, 91, 91, 54, 23, 233, 46, 190, 121, 122, 34, 86, 54}
// broadcast the transaction, wait to hear about it
waitForEvent(t, con, eid, true, func() {
broadcastTx(t, "JSONRPC", byteAddr, toAddr, nil, byteKey, amt, 0, 0)
broadcastTx(t, "JSONRPC", userByteAddr, toAddr, nil, userBytePriv, amt, 0, 0)
}, func(eid string, b []byte) error {
return nil
})
@ -213,9 +212,8 @@ func TestWSDoubleFire(t *testing.T) {
// create a contract, wait for the event, and send it a msg, validate the return
func TestWSCallWait(t *testing.T) {
byteAddr, _ := hex.DecodeString(userAddr)
con := newWSCon(t)
eid1 := types.EventStringAccInput(byteAddr)
eid1 := types.EventStringAccInput(userByteAddr)
subscribe(t, con, eid1)
defer func() {
unsubscribe(t, con, eid1)
@ -226,7 +224,7 @@ func TestWSCallWait(t *testing.T) {
var contractAddr []byte
// wait for the contract to be created
waitForEvent(t, con, eid1, true, func() {
_, receipt := broadcastTx(t, "JSONRPC", byteAddr, nil, code, byteKey, amt, 1000, 1000)
_, receipt := broadcastTx(t, "JSONRPC", userByteAddr, nil, code, userBytePriv, amt, 1000, 1000)
contractAddr = receipt.ContractAddr
}, unmarshalValidateCall(amt, returnCode))
@ -241,19 +239,18 @@ func TestWSCallWait(t *testing.T) {
// get the return value from a call
data := []byte{0x1} // just needs to be non empty for this to be a CallTx
waitForEvent(t, con, eid2, true, func() {
broadcastTx(t, "JSONRPC", byteAddr, contractAddr, data, byteKey, amt, 1000, 1000)
broadcastTx(t, "JSONRPC", userByteAddr, contractAddr, data, userBytePriv, amt, 1000, 1000)
}, unmarshalValidateCall(amt, returnVal))
}
// create a contract and send it a msg without waiting. wait for contract event
// and validate return
func TestWSCallNoWait(t *testing.T) {
byteAddr, _ := hex.DecodeString(userAddr)
con := newWSCon(t)
amt := uint64(10000)
code, _, returnVal := simpleContract()
_, receipt := broadcastTx(t, "JSONRPC", byteAddr, nil, code, byteKey, amt, 1000, 1000)
_, receipt := broadcastTx(t, "JSONRPC", userByteAddr, nil, code, userBytePriv, amt, 1000, 1000)
contractAddr := receipt.ContractAddr
// susbscribe to the new contract
@ -267,23 +264,22 @@ func TestWSCallNoWait(t *testing.T) {
// get the return value from a call
data := []byte{0x1} // just needs to be non empty for this to be a CallTx
waitForEvent(t, con, eid, true, func() {
broadcastTx(t, "JSONRPC", byteAddr, contractAddr, data, byteKey, amt, 1000, 1000)
broadcastTx(t, "JSONRPC", userByteAddr, contractAddr, data, userBytePriv, amt, 1000, 1000)
}, unmarshalValidateCall(amt, returnVal))
}
// create two contracts, one of which calls the other
func TestWSCallCall(t *testing.T) {
byteAddr, _ := hex.DecodeString(userAddr)
con := newWSCon(t)
amt := uint64(10000)
code, _, returnVal := simpleContract()
txid := new([]byte)
// deploy the two contracts
_, receipt := broadcastTx(t, "JSONRPC", byteAddr, nil, code, byteKey, amt, 1000, 1000)
_, receipt := broadcastTx(t, "JSONRPC", userByteAddr, nil, code, userBytePriv, amt, 1000, 1000)
contractAddr1 := receipt.ContractAddr
code, _, _ = simpleCallContract(contractAddr1)
_, receipt = broadcastTx(t, "JSONRPC", byteAddr, nil, code, byteKey, amt, 1000, 1000)
_, receipt = broadcastTx(t, "JSONRPC", userByteAddr, nil, code, userBytePriv, amt, 1000, 1000)
contractAddr2 := receipt.ContractAddr
// susbscribe to the new contracts
@ -300,7 +296,7 @@ func TestWSCallCall(t *testing.T) {
// call contract2, which should call contract1, and wait for ev1
data := []byte{0x1} // just needs to be non empty for this to be a CallTx
waitForEvent(t, con, eid1, true, func() {
tx, _ := broadcastTx(t, "JSONRPC", byteAddr, contractAddr2, data, byteKey, amt, 1000, 1000)
*txid = account.SignBytes(tx)
}, unmarshalValidateCallCall(byteAddr, returnVal, txid))
tx, _ := broadcastTx(t, "JSONRPC", userByteAddr, contractAddr2, data, userBytePriv, amt, 1000, 1000)
*txid = account.HashSignBytes(tx)
}, unmarshalValidateCallCall(userByteAddr, returnVal, txid))
}

+ 8
- 6
rpc/test/helpers.go View File

@ -28,10 +28,10 @@ var (
mempoolCount = 0
userAddr = "D7DFF9806078899C8DA3FE3633CC0BF3C6C2B1BB"
userPriv = "FDE3BD94CB327D19464027BA668194C5EFA46AE83E8419D7542CFF41F00C81972239C21C81EA7173A6C489145490C015E05D4B97448933B708A7EC5B7B4921E3"
userPub = "2239C21C81EA7173A6C489145490C015E05D4B97448933B708A7EC5B7B4921E3"
byteAddr, byteKey = initUserBytes()
userAddr = "D7DFF9806078899C8DA3FE3633CC0BF3C6C2B1BB"
userPriv = "FDE3BD94CB327D19464027BA668194C5EFA46AE83E8419D7542CFF41F00C81972239C21C81EA7173A6C489145490C015E05D4B97448933B708A7EC5B7B4921E3"
userPub = "2239C21C81EA7173A6C489145490C015E05D4B97448933B708A7EC5B7B4921E3"
userByteAddr, userBytePriv = initUserBytes()
clients = map[string]cclient.Client{
"JSONRPC": cclient.NewClient(requestAddr, "JSONRPC"),
@ -39,11 +39,13 @@ var (
}
)
// returns byte versions of address and private key
// type [64]byte needed by account.GenPrivAccountFromKey
func initUserBytes() ([]byte, [64]byte) {
byteAddr, _ := hex.DecodeString(userAddr)
var byteKey [64]byte
oh, _ := hex.DecodeString(userPriv)
copy(byteKey[:], oh)
userPrivByteSlice, _ := hex.DecodeString(userPriv)
copy(byteKey[:], userPrivByteSlice)
return byteAddr, byteKey
}


+ 12
- 17
rpc/test/tests.go View File

@ -2,14 +2,12 @@ package rpc
import (
"bytes"
"encoding/hex"
"fmt"
. "github.com/tendermint/tendermint/common"
"github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/types"
"testing"
//"time"
)
func testStatus(t *testing.T, typ string) {
@ -38,35 +36,34 @@ func testGenPriv(t *testing.T, typ string) {
}
func testGetAccount(t *testing.T, typ string) {
byteAddr, _ := hex.DecodeString(userAddr)
acc := getAccount(t, typ, byteAddr)
acc := getAccount(t, typ, userByteAddr)
if acc == nil {
t.Fatalf("Account was nil")
}
if bytes.Compare(acc.Address, byteAddr) != 0 {
t.Fatalf("Failed to get correct account. Got %x, expected %x", acc.Address, byteAddr)
if bytes.Compare(acc.Address, userByteAddr) != 0 {
t.Fatalf("Failed to get correct account. Got %x, expected %x", acc.Address, userByteAddr)
}
}
func testSignedTx(t *testing.T, typ string) {
amt := uint64(100)
toAddr := []byte{20, 143, 25, 63, 16, 177, 83, 29, 91, 91, 54, 23, 233, 46, 190, 121, 122, 34, 86, 54}
tx, priv := signTx(t, typ, byteAddr, toAddr, nil, byteKey, amt, 0, 0)
checkTx(t, byteAddr, priv, tx.(*types.SendTx))
tx, priv := signTx(t, typ, userByteAddr, toAddr, nil, userBytePriv, amt, 0, 0)
checkTx(t, userByteAddr, priv, tx.(*types.SendTx))
toAddr = []byte{20, 143, 24, 63, 16, 17, 83, 29, 90, 91, 52, 2, 0, 41, 190, 121, 122, 34, 86, 54}
tx, priv = signTx(t, typ, byteAddr, toAddr, nil, byteKey, amt, 0, 0)
checkTx(t, byteAddr, priv, tx.(*types.SendTx))
tx, priv = signTx(t, typ, userByteAddr, toAddr, nil, userBytePriv, amt, 0, 0)
checkTx(t, userByteAddr, priv, tx.(*types.SendTx))
toAddr = []byte{0, 0, 4, 0, 0, 4, 0, 0, 4, 91, 52, 2, 0, 41, 190, 121, 122, 34, 86, 54}
tx, priv = signTx(t, typ, byteAddr, toAddr, nil, byteKey, amt, 0, 0)
checkTx(t, byteAddr, priv, tx.(*types.SendTx))
tx, priv = signTx(t, typ, userByteAddr, toAddr, nil, userBytePriv, amt, 0, 0)
checkTx(t, userByteAddr, priv, tx.(*types.SendTx))
}
func testBroadcastTx(t *testing.T, typ string) {
amt := uint64(100)
toAddr := []byte{20, 143, 25, 63, 16, 177, 83, 29, 91, 91, 54, 23, 233, 46, 190, 121, 122, 34, 86, 54}
tx, receipt := broadcastTx(t, typ, byteAddr, toAddr, nil, byteKey, amt, 0, 0)
tx, receipt := broadcastTx(t, typ, userByteAddr, toAddr, nil, userBytePriv, amt, 0, 0)
if receipt.CreatesContract > 0 {
t.Fatal("This tx does not create a contract")
}
@ -102,7 +99,7 @@ func testGetStorage(t *testing.T, typ string) {
amt := uint64(1100)
code := []byte{0x60, 0x5, 0x60, 0x1, 0x55}
_, receipt := broadcastTx(t, typ, byteAddr, nil, code, byteKey, amt, 1000, 1000)
_, receipt := broadcastTx(t, typ, userByteAddr, nil, code, userBytePriv, amt, 1000, 1000)
if receipt.CreatesContract == 0 {
t.Fatal("This tx creates a contract")
}
@ -115,7 +112,6 @@ func testGetStorage(t *testing.T, typ string) {
}
// allow it to get mined
//time.Sleep(time.Second * 20)
waitForEvent(t, con, eid, true, func() {
}, func(eid string, b []byte) error {
return nil
@ -160,7 +156,7 @@ func testCall(t *testing.T, typ string) {
// create the contract
amt := uint64(6969)
code, _, _ := simpleContract()
_, receipt := broadcastTx(t, typ, byteAddr, nil, code, byteKey, amt, 1000, 1000)
_, receipt := broadcastTx(t, typ, userByteAddr, nil, code, userBytePriv, amt, 1000, 1000)
if receipt.CreatesContract == 0 {
t.Fatal("This tx creates a contract")
}
@ -173,7 +169,6 @@ func testCall(t *testing.T, typ string) {
}
// allow it to get mined
//time.Sleep(time.Second * 20)
waitForEvent(t, con, eid, true, func() {
}, func(eid string, b []byte) error {
return nil


+ 6
- 13
rpc/test/ws_helpers.go View File

@ -6,7 +6,6 @@ import (
"github.com/gorilla/websocket"
"github.com/tendermint/tendermint/binary"
"github.com/tendermint/tendermint/types"
"github.com/tendermint/tendermint/vm"
"testing"
)
@ -51,14 +50,14 @@ func unmarshalValidateSend(amt uint64, toAddr []byte) func(string, []byte) error
return fmt.Errorf("Eventid is not correct. Got %s, expected %s", response.Event, eid)
}
tx := response.Data
if bytes.Compare(tx.Inputs[0].Address, byteAddr) != 0 {
return fmt.Errorf("Senders do not match up! Got %x, expected %x", tx.Inputs[0].Address, byteAddr)
if bytes.Compare(tx.Inputs[0].Address, userByteAddr) != 0 {
return fmt.Errorf("Senders do not match up! Got %x, expected %x", tx.Inputs[0].Address, userByteAddr)
}
if tx.Inputs[0].Amount != amt {
return fmt.Errorf("Amt does not match up! Got %d, expected %d", tx.Inputs[0].Amount, amt)
}
if bytes.Compare(tx.Outputs[0].Address, toAddr) != 0 {
return fmt.Errorf("Receivers do not match up! Got %x, expected %x", tx.Outputs[0].Address, byteAddr)
return fmt.Errorf("Receivers do not match up! Got %x, expected %x", tx.Outputs[0].Address, userByteAddr)
}
return nil
}
@ -88,8 +87,8 @@ func unmarshalValidateCall(amt uint64, returnCode []byte) func(string, []byte) e
return fmt.Errorf(response.Data.Exception)
}
tx := response.Data.Tx
if bytes.Compare(tx.Input.Address, byteAddr) != 0 {
return fmt.Errorf("Senders do not match up! Got %x, expected %x", tx.Input.Address, byteAddr)
if bytes.Compare(tx.Input.Address, userByteAddr) != 0 {
return fmt.Errorf("Senders do not match up! Got %x, expected %x", tx.Input.Address, userByteAddr)
}
if tx.Input.Amount != amt {
return fmt.Errorf("Amt does not match up! Got %d, expected %d", tx.Input.Amount, amt)
@ -107,13 +106,7 @@ func unmarshalValidateCallCall(origin, returnCode []byte, txid *[]byte) func(str
// unmarshall and assert somethings
var response struct {
Event string
Data struct {
CallData *vm.CallData
Origin []byte
TxId []byte
Return []byte
Exception string
}
Data types.EventMsgCall
Error string
}
var err error


+ 2
- 4
state/block_cache.go View File

@ -53,9 +53,7 @@ func (cache *BlockCache) GetAccount(addr []byte) *ac.Account {
return acc
} else {
acc = cache.backend.GetAccount(addr)
if acc != nil {
cache.accounts[string(addr)] = accountInfo{acc, nil, false, false}
}
cache.accounts[string(addr)] = accountInfo{acc, nil, false, false}
return acc
}
}
@ -189,7 +187,7 @@ func (cache *BlockCache) Sync() {
}
} else {
if acc == nil {
panic(Fmt("Account should not be nil for addr: %x", addrStr))
continue
}
if storage != nil {
newStorageRoot := storage.Save()


+ 5
- 14
state/execution.go View File

@ -426,12 +426,12 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall, fireEvents bool) erro
txCache.UpdateAccount(caller) // because we adjusted by input above, and bumped nonce maybe.
txCache.UpdateAccount(callee) // because we adjusted by input above.
vmach := vm.NewVM(txCache, params, caller.Address, account.SignBytes(tx))
vmach := vm.NewVM(txCache, params, caller.Address, account.HashSignBytes(tx))
vmach.SetEventSwitch(_s.evsw)
// NOTE: Call() transfers the value from caller to callee iff call succeeds.
ret, err := vmach.Call(caller, callee, code, tx.Data, value, &gas)
var exception string
exception := ""
if err != nil {
exception = err.Error()
// Failure. Charge the gas fee. The 'value' was otherwise not transferred.
@ -440,7 +440,6 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall, fireEvents bool) erro
blockCache.UpdateAccount(inAcc)
// Throw away 'txCache' which holds incomplete updates (don't sync it).
} else {
exception = ""
log.Debug("Successful execution")
// Success
if createAccount {
@ -455,17 +454,9 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall, fireEvents bool) erro
if fireEvents {
// Fire Events for sender and receiver
// a separate event will be fired from vm for each
_s.evsw.FireEvent(types.EventStringAccInput(tx.Input.Address), struct {
Tx types.Tx
Return []byte
Exception string
}{tx, ret, exception})
_s.evsw.FireEvent(types.EventStringAccReceive(tx.Address), struct {
Tx types.Tx
Return []byte
Exception string
}{tx, ret, exception})
_s.evsw.FireEvent(types.EventStringAccInput(tx.Input.Address), types.EventMsgCallTx{tx, ret, exception})
_s.evsw.FireEvent(types.EventStringAccReceive(tx.Address), types.EventMsgCallTx{tx, ret, exception})
}
} else {
// The mempool does not call txs until


+ 27
- 0
types/events.go View File

@ -4,6 +4,8 @@ import (
"fmt"
)
// Functions to generate eventId strings
func EventStringAccInput(addr []byte) string {
return fmt.Sprintf("Acc/%x/Input", addr)
}
@ -40,6 +42,31 @@ func EventStringFork() string {
return "Fork"
}
// Most event messages are basic types (a block, a transaction)
// but some (an input to a call tx or a receive) are more exotic:
type EventMsgCallTx struct {
Tx Tx
Return []byte
Exception string
}
type CallData struct {
Caller []byte
Callee []byte
Data []byte
Value uint64
Gas uint64
}
type EventMsgCall struct {
CallData *CallData
Origin []byte
TxId []byte
Return []byte
Exception string
}
/*
Acc/XYZ/Input -> full tx or {full tx, return value, exception}
Acc/XYZ/Output -> full tx


+ 0
- 8
vm/types.go View File

@ -46,11 +46,3 @@ type Params struct {
BlockTime int64
GasLimit uint64
}
type CallData struct {
Caller []byte
Callee []byte
Data []byte
Value uint64
Gas uint64
}

+ 3
- 9
vm/vm.go View File

@ -91,17 +91,11 @@ func (vm *VM) Call(caller, callee *Account, code, input []byte, value uint64, ga
panic("Could not return value to caller")
}
}
// if callDepth is 0 the event is fired from ExecTx (along with the Input invent)
// if callDepth is 0 the event is fired from ExecTx (along with the Input event)
// otherwise, we fire from here.
if vm.callDepth != 0 && vm.evsw != nil {
vm.evsw.FireEvent(types.EventStringAccReceive(callee.Address.Prefix(20)), struct {
CallData *CallData
Origin []byte
TxId []byte
Return []byte
Exception string
}{
&CallData{caller.Address.Prefix(20), callee.Address.Prefix(20), input, value, *gas},
vm.evsw.FireEvent(types.EventStringAccReceive(callee.Address.Prefix(20)), types.EventMsgCall{
&types.CallData{caller.Address.Prefix(20), callee.Address.Prefix(20), input, value, *gas},
vm.origin.Prefix(20),
vm.txid,
output,


Loading…
Cancel
Save