Log not error; Remove Listener TMSP messages...; Make counter BigEndian
This commit is contained in:
parent
c4b87dcf14
commit
9696a71f6e
20
README.md
20
README.md
|
@ -12,9 +12,9 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog
|
|||
* __Arguments__:
|
||||
* `TxBytes ([]byte)`
|
||||
* __Returns__:
|
||||
* `RetCode (int8)`
|
||||
* `RetData ([]KVPair)`
|
||||
* `Error (string)`
|
||||
* `Code (int8)`
|
||||
* `Result ([]byte)`
|
||||
* `Log (string)`
|
||||
* __Usage__:<br/>
|
||||
Append and run a transaction. The transaction may or may not be final.
|
||||
|
||||
|
@ -22,15 +22,16 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog
|
|||
* __Arguments__:
|
||||
* `TxBytes ([]byte)`
|
||||
* __Returns__:
|
||||
* `RetCode (int8)`
|
||||
* `RetData ([]KVPair)`
|
||||
* `Error (string)`
|
||||
* `Code (int8)`
|
||||
* `Result ([]byte)`
|
||||
* `Log (string)`
|
||||
* __Usage__:<br/>
|
||||
Validate a transaction. This message should not mutate the state.
|
||||
|
||||
#### GetHash
|
||||
* __Returns__:
|
||||
* `Hash ([]byte)`
|
||||
* `Log (string)`
|
||||
* __Usage__:<br/>
|
||||
Return a Merkle root hash of the application state
|
||||
|
||||
|
@ -49,7 +50,7 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog
|
|||
* `Key (string)`
|
||||
* `Value (string)`
|
||||
* __Returns__:
|
||||
* `Error (string)`
|
||||
* `Log (string)`
|
||||
* __Usage__:<br/>
|
||||
Set application options. E.g. Key="mode", Value="mempool" for a mempool connection, or Key="mode", Value="consensus" for a consensus connection.
|
||||
Other options are application specific.
|
||||
|
@ -59,9 +60,10 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog
|
|||
### Jan 23th, 2016
|
||||
|
||||
* Added CheckTx/Query TMSP message types
|
||||
* Added RetData/Error fields to AppendTx/CheckTx/SetOption
|
||||
* Added Result/Log fields to AppendTx/CheckTx/SetOption
|
||||
* Removed Listener messages
|
||||
* Removed RetCode from ResponseSetOption and ResponseGetHash
|
||||
* Removed Code from ResponseSetOption and ResponseGetHash
|
||||
* Made examples BigEndian
|
||||
|
||||
### Jan 12th, 2016
|
||||
|
||||
|
|
|
@ -134,6 +134,7 @@ func (cli *TMSPClient) recvResponseRoutine() {
|
|||
}
|
||||
switch res := res.(type) {
|
||||
case tmsp.ResponseException:
|
||||
// XXX After setting cli.err, release waiters (e.g. reqres.Done())
|
||||
cli.StopForError(errors.New(res.Error))
|
||||
default:
|
||||
// log.Debug("Received response", "responseType", reflect.TypeOf(res), "response", res)
|
||||
|
@ -155,12 +156,6 @@ func (cli *TMSPClient) didRecvResponse(res tmsp.Response) error {
|
|||
cli.mtx.Lock()
|
||||
defer cli.mtx.Unlock()
|
||||
|
||||
// Special logic for events which have no corresponding requests.
|
||||
if _, ok := res.(tmsp.ResponseEvent); ok && cli.resCb != nil {
|
||||
cli.resCb(nil, res)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get the first reqRes
|
||||
next := cli.reqSent.Front()
|
||||
if next == nil {
|
||||
|
@ -210,27 +205,19 @@ func (cli *TMSPClient) GetHashAsync() {
|
|||
cli.queueRequest(tmsp.RequestGetHash{})
|
||||
}
|
||||
|
||||
func (cli *TMSPClient) AddListenerAsync(key string) {
|
||||
cli.queueRequest(tmsp.RequestAddListener{key})
|
||||
}
|
||||
|
||||
func (cli *TMSPClient) RemListenerAsync(key string) {
|
||||
cli.queueRequest(tmsp.RequestRemListener{key})
|
||||
}
|
||||
|
||||
func (cli *TMSPClient) QueryAsync(query []byte) {
|
||||
cli.queueRequest(tmsp.RequestQuery{query})
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
func (cli *TMSPClient) InfoSync() (info []string, err error) {
|
||||
func (cli *TMSPClient) InfoSync() (info string, err error) {
|
||||
reqres := cli.queueRequest(tmsp.RequestInfo{})
|
||||
cli.FlushSync()
|
||||
if cli.err != nil {
|
||||
return nil, cli.err
|
||||
return "", cli.err
|
||||
}
|
||||
return reqres.Response.(tmsp.ResponseInfo).Data, nil
|
||||
return reqres.Response.(tmsp.ResponseInfo).Info, nil
|
||||
}
|
||||
|
||||
func (cli *TMSPClient) FlushSync() error {
|
||||
|
@ -238,34 +225,44 @@ func (cli *TMSPClient) FlushSync() error {
|
|||
return cli.err
|
||||
}
|
||||
|
||||
func (cli *TMSPClient) AppendTxSync(tx []byte) error {
|
||||
func (cli *TMSPClient) AppendTxSync(tx []byte) (code tmsp.RetCode, result []byte, log string, err error) {
|
||||
reqres := cli.queueRequest(tmsp.RequestAppendTx{tx})
|
||||
cli.FlushSync()
|
||||
if cli.err != nil {
|
||||
return cli.err
|
||||
return tmsp.RetCodeInternalError, nil, "", cli.err
|
||||
}
|
||||
res := reqres.Response.(tmsp.ResponseAppendTx)
|
||||
return res.RetCode.Error()
|
||||
return res.Code, res.Result, res.Log, nil
|
||||
}
|
||||
|
||||
func (cli *TMSPClient) GetHashSync() (hash []byte, err error) {
|
||||
func (cli *TMSPClient) CheckTxSync(tx []byte) (code tmsp.RetCode, result []byte, log string, err error) {
|
||||
reqres := cli.queueRequest(tmsp.RequestCheckTx{tx})
|
||||
cli.FlushSync()
|
||||
if cli.err != nil {
|
||||
return tmsp.RetCodeInternalError, nil, "", cli.err
|
||||
}
|
||||
res := reqres.Response.(tmsp.ResponseCheckTx)
|
||||
return res.Code, res.Result, res.Log, nil
|
||||
}
|
||||
|
||||
func (cli *TMSPClient) GetHashSync() (hash []byte, log string, err error) {
|
||||
reqres := cli.queueRequest(tmsp.RequestGetHash{})
|
||||
cli.FlushSync()
|
||||
if cli.err != nil {
|
||||
return nil, cli.err
|
||||
return nil, "", cli.err
|
||||
}
|
||||
res := reqres.Response.(tmsp.ResponseGetHash)
|
||||
return res.Hash, res.RetCode.Error()
|
||||
return res.Hash, res.Log, nil
|
||||
}
|
||||
|
||||
func (cli *TMSPClient) QuerySync(query []byte) (result []byte, err error) {
|
||||
func (cli *TMSPClient) QuerySync(query []byte) (result []byte, log string, err error) {
|
||||
reqres := cli.queueRequest(tmsp.RequestQuery{query})
|
||||
cli.FlushSync()
|
||||
if cli.err != nil {
|
||||
return nil, cli.err
|
||||
return nil, "", cli.err
|
||||
}
|
||||
res := reqres.Response.(tmsp.ResponseQuery)
|
||||
return res.Result, res.RetCode.Error()
|
||||
return res.Result, res.Log, nil
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
|
@ -304,10 +301,6 @@ func resMatchesReq(req tmsp.Request, res tmsp.Response) (ok bool) {
|
|||
_, ok = res.(tmsp.ResponseCheckTx)
|
||||
case tmsp.RequestGetHash:
|
||||
_, ok = res.(tmsp.ResponseGetHash)
|
||||
case tmsp.RequestAddListener:
|
||||
_, ok = res.(tmsp.ResponseAddListener)
|
||||
case tmsp.RequestRemListener:
|
||||
_, ok = res.(tmsp.ResponseRemListener)
|
||||
case tmsp.RequestQuery:
|
||||
_, ok = res.(tmsp.ResponseQuery)
|
||||
default:
|
|
@ -2,6 +2,7 @@ package example
|
|||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
. "github.com/tendermint/go-common"
|
||||
"github.com/tendermint/tmsp/types"
|
||||
|
@ -17,66 +18,54 @@ func NewCounterApplication(serial bool) *CounterApplication {
|
|||
return &CounterApplication{serial: serial}
|
||||
}
|
||||
|
||||
func (app *CounterApplication) Echo(message string) string {
|
||||
return message
|
||||
func (app *CounterApplication) Info() string {
|
||||
return Fmt("hashes:%v, txs:%v", app.hashCount, app.txCount)
|
||||
}
|
||||
|
||||
func (app *CounterApplication) Info() []string {
|
||||
return []string{Fmt("hashes:%v, txs:%v", app.hashCount, app.txCount)}
|
||||
}
|
||||
|
||||
func (app *CounterApplication) SetOption(key string, value string) types.RetCode {
|
||||
func (app *CounterApplication) SetOption(key string, value string) (log string) {
|
||||
if key == "serial" && value == "on" {
|
||||
app.serial = true
|
||||
}
|
||||
return types.RetCodeOK
|
||||
return ""
|
||||
}
|
||||
|
||||
func (app *CounterApplication) AppendTx(tx []byte) ([]types.Event, types.RetCode) {
|
||||
func (app *CounterApplication) AppendTx(tx []byte) (code types.RetCode, result []byte, log string) {
|
||||
if app.serial {
|
||||
tx8 := make([]byte, 8)
|
||||
copy(tx8, tx)
|
||||
txValue := binary.LittleEndian.Uint64(tx8)
|
||||
copy(tx8[len(tx8)-len(tx):], tx)
|
||||
txValue := binary.BigEndian.Uint64(tx8)
|
||||
if txValue != uint64(app.txCount) {
|
||||
return nil, types.RetCodeBadNonce
|
||||
return types.RetCodeBadNonce, nil, fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.txCount, txValue)
|
||||
}
|
||||
}
|
||||
app.txCount += 1
|
||||
return nil, types.RetCodeOK
|
||||
return types.RetCodeOK, nil, ""
|
||||
}
|
||||
|
||||
func (app *CounterApplication) CheckTx(tx []byte) types.RetCode {
|
||||
func (app *CounterApplication) CheckTx(tx []byte) (code types.RetCode, result []byte, log string) {
|
||||
if app.serial {
|
||||
tx8 := make([]byte, 8)
|
||||
copy(tx8, tx)
|
||||
txValue := binary.LittleEndian.Uint64(tx8)
|
||||
copy(tx8[len(tx8)-len(tx):], tx)
|
||||
txValue := binary.BigEndian.Uint64(tx8)
|
||||
if txValue < uint64(app.txCount) {
|
||||
return types.RetCodeBadNonce
|
||||
return types.RetCodeBadNonce, nil, fmt.Sprintf("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)
|
||||
}
|
||||
}
|
||||
return types.RetCodeOK
|
||||
return types.RetCodeOK, nil, ""
|
||||
}
|
||||
|
||||
func (app *CounterApplication) GetHash() ([]byte, types.RetCode) {
|
||||
func (app *CounterApplication) GetHash() (hash []byte, log string) {
|
||||
app.hashCount += 1
|
||||
|
||||
if app.txCount == 0 {
|
||||
return nil, types.RetCodeOK
|
||||
return nil, ""
|
||||
} else {
|
||||
hash := make([]byte, 32)
|
||||
binary.LittleEndian.PutUint64(hash, uint64(app.txCount))
|
||||
return hash, types.RetCodeOK
|
||||
hash := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(hash, uint64(app.txCount))
|
||||
return hash, ""
|
||||
}
|
||||
}
|
||||
|
||||
func (app *CounterApplication) AddListener(key string) types.RetCode {
|
||||
return types.RetCodeOK
|
||||
}
|
||||
|
||||
func (app *CounterApplication) RemListener(key string) types.RetCode {
|
||||
return types.RetCodeOK
|
||||
}
|
||||
|
||||
func (app *CounterApplication) Query(query []byte) ([]byte, types.RetCode) {
|
||||
return nil, types.RetCodeOK
|
||||
func (app *CounterApplication) Query(query []byte) (result []byte, log string) {
|
||||
return nil, fmt.Sprintf("Query is not supported")
|
||||
}
|
||||
|
|
|
@ -18,40 +18,28 @@ func NewDummyApplication() *DummyApplication {
|
|||
return &DummyApplication{state: state}
|
||||
}
|
||||
|
||||
func (app *DummyApplication) Echo(message string) string {
|
||||
return message
|
||||
func (app *DummyApplication) Info() string {
|
||||
return Fmt("size:%v", app.state.Size())
|
||||
}
|
||||
|
||||
func (app *DummyApplication) Info() []string {
|
||||
return []string{Fmt("size:%v", app.state.Size())}
|
||||
func (app *DummyApplication) SetOption(key string, value string) (log string) {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (app *DummyApplication) SetOption(key string, value string) types.RetCode {
|
||||
return types.RetCodeOK
|
||||
}
|
||||
|
||||
func (app *DummyApplication) AppendTx(tx []byte) ([]types.Event, types.RetCode) {
|
||||
func (app *DummyApplication) AppendTx(tx []byte) (code types.RetCode, result []byte, log string) {
|
||||
app.state.Set(tx, tx)
|
||||
return nil, types.RetCodeOK
|
||||
return types.RetCodeOK, nil, ""
|
||||
}
|
||||
|
||||
func (app *DummyApplication) CheckTx(tx []byte) types.RetCode {
|
||||
return types.RetCodeOK // all txs are valid
|
||||
func (app *DummyApplication) CheckTx(tx []byte) (code types.RetCode, result []byte, log string) {
|
||||
return types.RetCodeOK, nil, ""
|
||||
}
|
||||
|
||||
func (app *DummyApplication) GetHash() ([]byte, types.RetCode) {
|
||||
hash := app.state.Hash()
|
||||
return hash, types.RetCodeOK
|
||||
func (app *DummyApplication) GetHash() (hash []byte, log string) {
|
||||
hash = app.state.Hash()
|
||||
return hash, ""
|
||||
}
|
||||
|
||||
func (app *DummyApplication) AddListener(key string) types.RetCode {
|
||||
return types.RetCodeOK
|
||||
}
|
||||
|
||||
func (app *DummyApplication) RemListener(key string) types.RetCode {
|
||||
return types.RetCodeOK
|
||||
}
|
||||
|
||||
func (app *DummyApplication) Query(query []byte) ([]byte, types.RetCode) {
|
||||
return nil, types.RetCodeOK
|
||||
func (app *DummyApplication) Query(query []byte) (result []byte, log string) {
|
||||
return nil, "Query not supported"
|
||||
}
|
||||
|
|
|
@ -44,8 +44,8 @@ func TestStream(t *testing.T) {
|
|||
switch res := res.(type) {
|
||||
case types.ResponseAppendTx:
|
||||
counter += 1
|
||||
if res.RetCode != types.RetCodeOK {
|
||||
t.Error("AppendTx failed with ret_code", res.RetCode)
|
||||
if res.Code != types.RetCodeOK {
|
||||
t.Error("AppendTx failed with ret_code", res.Code)
|
||||
}
|
||||
if counter > numAppendTxs {
|
||||
t.Fatal("Too many AppendTx responses")
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
node_modules
|
|
@ -1,6 +1,9 @@
|
|||
server = require("./server")
|
||||
wire = require("./wire")
|
||||
util = require("util")
|
||||
var server = require("./server");
|
||||
var wire = require("js-wire");
|
||||
var util = require("util");
|
||||
var msg = require("./msgs");
|
||||
var types = require("./types");
|
||||
|
||||
|
||||
function CounterApp(){
|
||||
this.hashCount = 0;
|
||||
|
@ -8,75 +11,65 @@ function CounterApp(){
|
|||
this.serial = false;
|
||||
};
|
||||
|
||||
CounterApp.prototype.echo = function(msg){
|
||||
return {"response": msg, "ret_code":0}
|
||||
CounterApp.prototype.info = function(cb) {
|
||||
return cb(util.format("hashes:%d, txs:%d", this.hashCount, this.txCount));
|
||||
}
|
||||
|
||||
CounterApp.prototype.info = function(){
|
||||
return {"response": [util.format("hashes:%d, txs:%d", this.hashCount, this.txCount)]}
|
||||
}
|
||||
|
||||
CounterApp.prototype.set_option = function(key, value){
|
||||
if (key == "serial" && value == "on"){
|
||||
CounterApp.prototype.set_option = function(cb, key, value) {
|
||||
if (key == "serial" && value == "on") {
|
||||
this.serial = true;
|
||||
}
|
||||
return {"ret_code":0}
|
||||
return cb("");
|
||||
}
|
||||
|
||||
CounterApp.prototype.append_tx = function(txBytes){
|
||||
CounterApp.prototype.append_tx = function(cb, txBytes) {
|
||||
if (this.serial) {
|
||||
txByteArray = new Buffer(txBytes)
|
||||
if (txBytes.length >= 2 && txBytes.slice(0, 2) == "0x") {
|
||||
txByteArray = wire.hex2bytes(txBytes.slice(2));
|
||||
var hexString = txBytes.toString("ascii", 2);
|
||||
var hexBytes = new Buffer(hexString, "hex");
|
||||
txBytes = hexBytes;
|
||||
}
|
||||
r = new msg.buffer(txByteArray)
|
||||
txValue = wire.decode_big_endian(r, txBytes.length)
|
||||
var txValue = txBytes.readIntBE(0, txBytes.length);
|
||||
if (txValue != this.txCount){
|
||||
return {"ret_code":6}
|
||||
return cb(types.RetCodeInvalidNonce, "", "Nonce is invalid");
|
||||
}
|
||||
}
|
||||
this.txCount += 1;
|
||||
return {"ret_code":0} // TODO: return events
|
||||
return cb(types.RetCodeOK, "", "");
|
||||
}
|
||||
|
||||
CounterApp.prototype.check_tx = function(txBytes){
|
||||
CounterApp.prototype.check_tx = function(cb, txBytes) {
|
||||
if (this.serial) {
|
||||
txByteArray = new Buffer(txBytes)
|
||||
if (txBytes.length >= 2 && txBytes.slice(0, 2) == "0x") {
|
||||
txByteArray = wire.hex2bytes(txBytes.slice(2));
|
||||
var hexString = txBytes.toString("ascii", 2);
|
||||
var hexBytes = new Buffer(hexString, "hex");
|
||||
txBytes = hexBytes;
|
||||
}
|
||||
r = new msg.buffer(txByteArray)
|
||||
txValue = wire.decode_big_endian(r, txBytes.length)
|
||||
var txValue = txBytes.readIntBE(0, txBytes.length);
|
||||
if (txValue < this.txCount){
|
||||
return {"ret_code":6}
|
||||
return cb(types.RetCodeInvalidNonce, "", "Nonce is too low");
|
||||
}
|
||||
}
|
||||
return {"ret_code":0}
|
||||
this.txCount += 1;
|
||||
return cb(types.RetCodeOK, "", "");
|
||||
}
|
||||
|
||||
CounterApp.prototype.get_hash = function(){
|
||||
CounterApp.prototype.get_hash = function(cb) {
|
||||
this.hashCount += 1;
|
||||
if (this.txCount == 0){
|
||||
return {"response": "", "ret_code":0}
|
||||
return cb("", "Zero tx count; hash is empth");
|
||||
}
|
||||
h = wire.encode_big_endian(this.txCount, 8);
|
||||
h = wire.reverse(h); // TODO
|
||||
return {"response": h.toString(), "ret_code":0}
|
||||
var buf = new Buffer(8);
|
||||
buf.writeIntBE(this.txCount, 0, 8);
|
||||
cb(buf, "");
|
||||
}
|
||||
|
||||
CounterApp.prototype.add_listener = function(){
|
||||
return {"ret_code":0}
|
||||
CounterApp.prototype.query = function(cb) {
|
||||
return cb("", "Query not yet supporrted");
|
||||
}
|
||||
|
||||
CounterApp.prototype.rm_listener = function(){
|
||||
return {"ret_code":0}
|
||||
}
|
||||
|
||||
CounterApp.prototype.event = function(){
|
||||
}
|
||||
|
||||
console.log("Counter app in Javascript")
|
||||
console.log("Counter app in Javascript");
|
||||
|
||||
var app = new CounterApp();
|
||||
var appServer = new server.AppServer(app);
|
||||
appServer.server.listen(46658)
|
||||
appServer.server.listen(46658);
|
||||
|
|
|
@ -1,59 +1,88 @@
|
|||
wire = require("./wire")
|
||||
var wire = require("js-wire");
|
||||
var types = require("./types");
|
||||
|
||||
var readRequestInfo = function(r) { return []; };
|
||||
var readRequestSetOption = function(r) { return [r.readString(), r.readString()]; };
|
||||
var readRequestAppendTx = function(r) { return [r.readByteArray()]; };
|
||||
var readRequestCheckTx = function(r) { return [r.readByteArray()]; };
|
||||
var readRequestGetHash = function(r) { return []; };
|
||||
var readRequestQuery = function(r) { return [r.readByteArray()]; };
|
||||
|
||||
var runOnce = function(name, f) {
|
||||
var ran = false;
|
||||
return function() {
|
||||
if (ran) {
|
||||
console.log("Error: response was already written for "+name);
|
||||
return
|
||||
} else {
|
||||
ran = true;
|
||||
}
|
||||
return f.apply(this, arguments);
|
||||
};
|
||||
};
|
||||
|
||||
var makeWriteResponseInfo = function(w, cb) { return runOnce("info", function(info) {
|
||||
w.writeUint8(types.ResponseTypeInfo);
|
||||
w.writeString(info);
|
||||
cb(w);
|
||||
});};
|
||||
var makeWriteResponseSetOption = function(w, cb) { return runOnce("set_option", function(log) {
|
||||
w.writeUint8(types.ResponseTypeSetOption);
|
||||
w.writeString(log);
|
||||
cb(w);
|
||||
});};
|
||||
var makeWriteResponseAppendTx = function(w, cb) { return runOnce("append_tx", function(code, result, log) {
|
||||
w.writeUint8(types.ResponseTypeAppendTx);
|
||||
w.writeUint8(code);
|
||||
w.writeByteArray(result);
|
||||
w.writeString(log);
|
||||
cb(w);
|
||||
});};
|
||||
var makeWriteResponseCheckTx = function(w, cb) { return runOnce("check_tx", function(code, result, log) {
|
||||
w.writeUint8(types.ResponseTypeCheckTx);
|
||||
w.writeUint8(code);
|
||||
w.writeByteArray(result);
|
||||
w.writeString(log);
|
||||
cb(w);
|
||||
});};
|
||||
var makeWriteResponseGetHash = function(w, cb) { return runOnce("get_hash", function(hash, log) {
|
||||
w.writeUint8(types.ResponseTypeGetHash);
|
||||
w.writeByteArray(hash);
|
||||
w.writeString(log);
|
||||
cb(w);
|
||||
});};
|
||||
var makeWriteResponseQuery = function(w, cb) { return runOnce("query", function(result, log) {
|
||||
w.writeUint8(types.ResponseTypeQuery);
|
||||
w.writeByteArray(result);
|
||||
w.writeString(log);
|
||||
cb(w);
|
||||
});};
|
||||
|
||||
module.exports = {
|
||||
types : {
|
||||
0x01 : "echo",
|
||||
0x02 : "flush",
|
||||
0x03 : "info",
|
||||
0x04 : "set_option",
|
||||
0x21 : "append_tx",
|
||||
0x22 : "check_tx",
|
||||
0x23 : "get_hash",
|
||||
0x24 : "add_listener",
|
||||
0x25 : "rm_listener",
|
||||
},
|
||||
decoder : RequestDecoder,
|
||||
buffer: BytesBuffer
|
||||
}
|
||||
|
||||
function RequestDecoder(buf){
|
||||
this.buf= buf
|
||||
}
|
||||
|
||||
var decode_string = wire.decode_string
|
||||
|
||||
// return nothing, one thing, or a list of things
|
||||
RequestDecoder.prototype.echo = function(){ return decode_string(this.buf) };
|
||||
RequestDecoder.prototype.flush = function(){};
|
||||
RequestDecoder.prototype.info = function(){};
|
||||
RequestDecoder.prototype.set_option = function(){ return [decode_string(this.buf), decode_string(this.buf)] };
|
||||
RequestDecoder.prototype.append_tx = function(){ return decode_string(this.buf)};
|
||||
RequestDecoder.prototype.check_tx = function(){ return decode_string(this.buf)};
|
||||
RequestDecoder.prototype.get_hash = function(){ };
|
||||
RequestDecoder.prototype.add_listener = function(){ }; // TODO
|
||||
RequestDecoder.prototype.rm_listener = function(){ }; // TODO
|
||||
|
||||
// buffered reader with read(n) method
|
||||
function BytesBuffer(buf){
|
||||
this.buf = buf
|
||||
}
|
||||
|
||||
BytesBuffer.prototype.read = function(n){
|
||||
b = this.buf.slice(0, n)
|
||||
this.buf = this.buf.slice(n)
|
||||
return b
|
||||
types : {
|
||||
0x01 : "echo",
|
||||
0x02 : "flush",
|
||||
0x03 : "info",
|
||||
0x04 : "set_option",
|
||||
0x21 : "append_tx",
|
||||
0x22 : "check_tx",
|
||||
0x23 : "get_hash",
|
||||
0x24 : "query",
|
||||
},
|
||||
readers : {
|
||||
"info": readRequestInfo,
|
||||
"set_option": readRequestSetOption,
|
||||
"append_tx": readRequestAppendTx,
|
||||
"check_tx": readRequestCheckTx,
|
||||
"get_hash": readRequestGetHash,
|
||||
"query": readRequestQuery,
|
||||
},
|
||||
writerGenerators: {
|
||||
"info": makeWriteResponseInfo,
|
||||
"set_option": makeWriteResponseSetOption,
|
||||
"append_tx": makeWriteResponseAppendTx,
|
||||
"check_tx": makeWriteResponseCheckTx,
|
||||
"get_hash": makeWriteResponseGetHash,
|
||||
"query": makeWriteResponseQuery,
|
||||
},
|
||||
};
|
||||
|
||||
BytesBuffer.prototype.write = function(buf){
|
||||
this.buf = Buffer.concat([this.buf, buf]);
|
||||
};
|
||||
|
||||
|
||||
BytesBuffer.prototype.size = function(){
|
||||
return this.buf.length
|
||||
}
|
||||
|
||||
BytesBuffer.prototype.peek = function(){
|
||||
return this.buf[0]
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "example",
|
||||
"version": "0.0.1",
|
||||
"description": "Example javascript TMSP application",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"js-wire": "0.0.2"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,126 +1,141 @@
|
|||
var net = require("net");
|
||||
var wire = require("js-wire");
|
||||
var msg = require("./msgs");
|
||||
var types = require("./types");
|
||||
|
||||
// Load the TCP Library
|
||||
net = require('net');
|
||||
msg = require('./msgs');
|
||||
wire = require("./wire")
|
||||
var maxWriteBufferLength = 4096; // Any more and flush
|
||||
|
||||
// Takes an application and handles tmsp connection
|
||||
// Takes an application and handles TMSP connection
|
||||
// which invoke methods on the app
|
||||
function AppServer(app){
|
||||
// set the app for the socket handler
|
||||
this.app = app;
|
||||
// set the app for the socket handler
|
||||
this.app = app;
|
||||
|
||||
// create a server by providing callback for
|
||||
// accepting new connection and callbacks for
|
||||
// connection events ('data', 'end', etc.)
|
||||
this.createServer()
|
||||
// create a server by providing callback for
|
||||
// accepting new connection and callbacks for
|
||||
// connection events ('data', 'end', etc.)
|
||||
this.createServer();
|
||||
}
|
||||
|
||||
AppServer.prototype.createServer = function() {
|
||||
var app = this.app;
|
||||
|
||||
// Define the socket handler
|
||||
this.server = net.createServer(function(socket) {
|
||||
socket.name = socket.remoteAddress + ":" + socket.remotePort;
|
||||
console.log("new connection from", socket.name);
|
||||
|
||||
var conn = new Connection(socket, function(msgBytes, cb) {
|
||||
var r = new wire.Reader(msgBytes);
|
||||
|
||||
// Now we can decode
|
||||
var typeByte = r.readByte();
|
||||
var reqType = msg.types[typeByte];
|
||||
|
||||
// Special messages.
|
||||
// NOTE: msgs are length prefixed
|
||||
if (reqType == "flush") {
|
||||
var w = new wire.Writer();
|
||||
w.writeByte(types.ResponseTypeFlush);
|
||||
conn.writeMessage(w.getBuffer());
|
||||
conn.flush();
|
||||
return cb();
|
||||
} else if (reqType == "echo") {
|
||||
var message = r.readString();
|
||||
var w = new wire.Writer();
|
||||
w.writeByte(types.ResponseTypeEcho);
|
||||
w.writeString(message);
|
||||
conn.writeMessage(w.getBuffer());
|
||||
return cb();
|
||||
}
|
||||
|
||||
// Make callback by wrapping cp
|
||||
var resCb = msg.writerGenerators[reqType](new wire.Writer(), function(w) {
|
||||
conn.writeMessage(w.getBuffer());
|
||||
return cb();
|
||||
});
|
||||
|
||||
// Decode arguments
|
||||
var args = msg.readers[reqType](r);
|
||||
args.unshift(resCb);
|
||||
|
||||
// Call function
|
||||
var res = app[reqType].apply(app, args);
|
||||
if (res != undefined) {
|
||||
console.log("Message handler shouldn't return anything!");
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
function Connection(socket, msgCb) {
|
||||
this.socket = socket;
|
||||
this.recvBuf = new Buffer(0);
|
||||
this.sendBuf = new Buffer(0);
|
||||
this.msgCb = msgCb;
|
||||
this.waitingResult = false;
|
||||
var conn = this;
|
||||
|
||||
// Handle TMSP requests.
|
||||
socket.on('data', function(data) {
|
||||
conn.appendData(data);
|
||||
});
|
||||
socket.on('end', function() {
|
||||
console.log("connection ended");
|
||||
});
|
||||
}
|
||||
|
||||
Connection.prototype.appendData = function(bytes) {
|
||||
var conn = this;
|
||||
if (bytes.length > 0) {
|
||||
this.recvBuf = Buffer.concat([this.recvBuf, new Buffer(bytes)]);
|
||||
}
|
||||
if (this.waitingResult) {
|
||||
return;
|
||||
}
|
||||
var r = new wire.Reader(this.recvBuf);
|
||||
var msg;
|
||||
try {
|
||||
msg = r.readByteArray();
|
||||
} catch(e) {
|
||||
return;
|
||||
}
|
||||
this.recvBuf = r.buf.slice(r.offset);
|
||||
this.waitingResult = true;
|
||||
this.socket.pause();
|
||||
//try {
|
||||
this.msgCb(msg, function() {
|
||||
// This gets called after msg handler is finished with response.
|
||||
conn.waitingResult = false;
|
||||
conn.socket.resume();
|
||||
if (conn.recvBuf.length > 0) {
|
||||
conn.appendData("");
|
||||
}
|
||||
});
|
||||
//} catch(e) {
|
||||
// console.log("FATAL ERROR: ", e);
|
||||
//}
|
||||
};
|
||||
|
||||
Connection.prototype.writeMessage = function(msgBytes) {
|
||||
var msgLength = wire.uvarintSize(msgBytes.length);
|
||||
var buf = new Buffer(1+msgLength+msgBytes.length);
|
||||
var w = new wire.Writer(buf);
|
||||
w.writeByteArray(msgBytes); // TODO technically should be writeVarint
|
||||
this.sendBuf = Buffer.concat([this.sendBuf, w.getBuffer()]);
|
||||
if (this.sendBuf.length >= maxWriteBufferLength) {
|
||||
this.flush();
|
||||
}
|
||||
};
|
||||
|
||||
Connection.prototype.flush = function() {
|
||||
var n = this.socket.write(this.sendBuf);
|
||||
this.sendBuf = new Buffer(0);
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
module.exports = { AppServer: AppServer };
|
||||
|
||||
AppServer.prototype.createServer = function(){
|
||||
app = this.app
|
||||
conns = {} // map sockets to their state
|
||||
|
||||
// define the socket handler
|
||||
this.server = net.createServer(function(socket){
|
||||
socket.name = socket.remoteAddress + ":" + socket.remotePort
|
||||
console.log("new connection from", socket.name)
|
||||
|
||||
var conn = {
|
||||
recBuf: new msg.buffer(new Buffer(0)),
|
||||
resBuf: new msg.buffer(new Buffer(0)),
|
||||
msgLength: 0,
|
||||
inProgress: false
|
||||
}
|
||||
conns[socket] = conn
|
||||
|
||||
// Handle tmsp requests.
|
||||
socket.on('data', function (data) {
|
||||
|
||||
if (data.length == 0){
|
||||
// TODO err
|
||||
console.log("empty data!")
|
||||
return
|
||||
}
|
||||
conn = conns[socket]
|
||||
|
||||
// we received data. append it
|
||||
conn.recBuf.write(data)
|
||||
|
||||
while ( conn.recBuf.size() > 0 ){
|
||||
|
||||
if (conn.msgLength == 0){
|
||||
ll = conn.recBuf.peek();
|
||||
if (conn.recBuf.size() < 1 + ll){
|
||||
// don't have enough bytes to read length yet
|
||||
return
|
||||
}
|
||||
conn.msgLength = wire.decode_varint(conn.recBuf)
|
||||
}
|
||||
|
||||
if (conn.recBuf.size() < conn.msgLength) {
|
||||
// don't have enough to decode the message
|
||||
return
|
||||
}
|
||||
|
||||
// now we can decode
|
||||
typeByte = conn.recBuf.read(1);
|
||||
resTypeByte = typeByte[0] + 0x10
|
||||
reqType = msg.types[typeByte[0]];
|
||||
|
||||
if (reqType == "flush"){
|
||||
// msgs are length prefixed
|
||||
conn.resBuf.write(wire.encode(1));
|
||||
conn.resBuf.write(new Buffer([resTypeByte]))
|
||||
n = socket.write(conn.resBuf.buf);
|
||||
conn.msgLength = 0;
|
||||
conn.resBuf = new msg.buffer(new Buffer(0));
|
||||
return
|
||||
}
|
||||
|
||||
// decode args
|
||||
decoder = new msg.decoder(conn.recBuf);
|
||||
args = decoder[reqType]();
|
||||
|
||||
// done decoding
|
||||
conn.msgLength = 0
|
||||
|
||||
var res = function(){
|
||||
if (args == null){
|
||||
return app[reqType]();
|
||||
} else if (Array.isArray(args)){
|
||||
return app[reqType].apply(app, args);
|
||||
} else {
|
||||
return app[reqType](args)
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
var retCode = res["ret_code"]
|
||||
var res = res["response"]
|
||||
|
||||
if (retCode != null && retCode != 0){
|
||||
console.log("non-zero ret code", retCode)
|
||||
}
|
||||
|
||||
|
||||
if (reqType == "echo" || reqType == "info"){
|
||||
enc = Buffer.concat([new Buffer([resTypeByte]), wire.encode(res)]);
|
||||
// length prefixed
|
||||
conn.resBuf.write(wire.encode(enc.length));
|
||||
conn.resBuf.write(enc);
|
||||
} else {
|
||||
enc = Buffer.concat([new Buffer([resTypeByte]), wire.encode(retCode), wire.encode(res)]);
|
||||
conn.resBuf.write(wire.encode(enc.length));
|
||||
conn.resBuf.write(enc);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('end', function () {
|
||||
console.log("connection ended")
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
module.exports = {
|
||||
RetCodeOK: 0,
|
||||
RetCodeInternalError: 1,
|
||||
RetCodeUnauthorized: 2,
|
||||
RetCodeInsufficientFees: 3,
|
||||
RetCodeUnknownRequest: 4,
|
||||
RetCodeEncodingError: 5,
|
||||
RetCodeNonce: 6,
|
||||
|
||||
RequestTypeEcho: 0x01,
|
||||
RequestTypeFlush: 0x02,
|
||||
RequestTypeInfo: 0x03,
|
||||
RequestTypeSetOption: 0x04,
|
||||
RequestTypeAppendTx: 0x21,
|
||||
RequestTypeCheckTx: 0x22,
|
||||
RequestTypeGetHash: 0x23,
|
||||
RequestTypeQuery: 0x24,
|
||||
|
||||
ResponseTypeEcho: 0x11,
|
||||
ResponseTypeFlush: 0x12,
|
||||
ResponseTypeInfo: 0x13,
|
||||
ResponseTypeSetOption: 0x14,
|
||||
ResponseTypeAppendTx: 0x31,
|
||||
ResponseTypeCheckTx: 0x32,
|
||||
ResponseTypeGetHash: 0x33,
|
||||
ResponseTypeQuery: 0x34,
|
||||
};
|
|
@ -1,111 +0,0 @@
|
|||
module.exports = {
|
||||
decode_string: decode_string,
|
||||
decode_varint: decode_varint,
|
||||
decode_big_endian: decode_big_endian,
|
||||
encode_big_endian: encode_big_endian,
|
||||
encode: encode,
|
||||
reverse: reverse,
|
||||
}
|
||||
|
||||
function reverse(buf){
|
||||
for (var i = 0; i < buf.length/2; i++){
|
||||
a = buf[i];
|
||||
b = buf[buf.length-1 - i];
|
||||
buf[i] = b;
|
||||
buf[buf.length-1 - i] = a;
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
||||
function uvarint_size(i){
|
||||
if (i == 0){
|
||||
return 0
|
||||
}
|
||||
|
||||
for(var j = 1; j < 9; j++) {
|
||||
if ( i < 1<<j*8 ) {
|
||||
return j
|
||||
}
|
||||
}
|
||||
|
||||
return 8
|
||||
}
|
||||
|
||||
function encode_big_endian(i, size){
|
||||
if (size == 0){
|
||||
return new Buffer(0);
|
||||
}
|
||||
b = encode_big_endian(Math.floor(i/256), size-1);
|
||||
return Buffer.concat([b, new Buffer([i%256])]);
|
||||
}
|
||||
|
||||
function decode_big_endian(reader, size){
|
||||
if (size == 0){ return 0 }
|
||||
firstByte = reader.read(1)[0];
|
||||
return firstByte*(Math.pow(256, size-1)) + decode_big_endian(reader, size-1)
|
||||
}
|
||||
|
||||
function encode_string(s){
|
||||
size = encode_varint(s.length);
|
||||
return Buffer.concat([size, new Buffer(s)])
|
||||
}
|
||||
|
||||
function decode_string(reader){
|
||||
length = decode_varint(reader);
|
||||
return reader.read(length).toString()
|
||||
}
|
||||
|
||||
function encode_varint(i){
|
||||
var negate = false;
|
||||
if (i < 0){
|
||||
negate = true;
|
||||
i = -i;
|
||||
}
|
||||
size = uvarint_size(i);
|
||||
if (size == 0){
|
||||
return new Buffer([0])
|
||||
}
|
||||
|
||||
big_end = encode_big_endian(i, size);
|
||||
if (negate){ size += 0xF0 }
|
||||
var buf = new Buffer([size]);
|
||||
return Buffer.concat([buf, big_end])
|
||||
}
|
||||
|
||||
function decode_varint(reader){
|
||||
size = reader.read(1)[0];
|
||||
if (size == 0 ){
|
||||
return 0
|
||||
}
|
||||
var negate = false;
|
||||
if (size > 0xF0){ negate = true }
|
||||
if (negate) { size = size - 0xF0 }
|
||||
i = decode_big_endian(reader, size);
|
||||
if (negate) { i = i * -1}
|
||||
return i
|
||||
}
|
||||
|
||||
function encode_list(l){
|
||||
var l2 = l.map(encode);
|
||||
var buf = new Buffer(encode_varint(l2.length));
|
||||
return Buffer.concat([buf, Buffer.concat(l2)]);
|
||||
}
|
||||
|
||||
function encode(b){
|
||||
if (b == null){
|
||||
return Buffer(0)
|
||||
} else if (typeof b == "number"){
|
||||
return encode_varint(b)
|
||||
} else if (typeof b == "string"){
|
||||
return encode_string(b)
|
||||
} else if (Array.isArray(b)){
|
||||
return encode_list(b)
|
||||
} else{
|
||||
console.log("UNSUPPORTED TYPE!", typeof b, b)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -8,6 +8,7 @@ from tmsp.reader import BytesBuffer
|
|||
class CounterApplication():
|
||||
|
||||
def __init__(self):
|
||||
sys.exit("The python example is out of date. Upgrading the Python examples is currently left as an exercise to you.")
|
||||
self.hashCount = 0
|
||||
self.txCount = 0
|
||||
self.serial = False
|
||||
|
|
|
@ -8,6 +8,7 @@ from tmsp.reader import BytesBuffer
|
|||
class CounterApplication():
|
||||
|
||||
def __init__(self):
|
||||
sys.exit("The python example is out of date. Upgrading the Python examples is currently left as an exercise to you.")
|
||||
self.hashCount = 0
|
||||
self.txCount = 0
|
||||
self.serial = False
|
||||
|
|
|
@ -99,37 +99,27 @@ func handleRequests(mtx *sync.Mutex, app types.Application, closeConn chan error
|
|||
func handleRequest(app types.Application, req types.Request, responses chan<- types.Response) {
|
||||
switch req := req.(type) {
|
||||
case types.RequestEcho:
|
||||
msg := app.Echo(req.Message)
|
||||
responses <- types.ResponseEcho{msg}
|
||||
responses <- types.ResponseEcho{req.Message}
|
||||
case types.RequestFlush:
|
||||
responses <- types.ResponseFlush{}
|
||||
case types.RequestInfo:
|
||||
data := app.Info()
|
||||
responses <- types.ResponseInfo{data}
|
||||
case types.RequestSetOption:
|
||||
retCode := app.SetOption(req.Key, req.Value)
|
||||
responses <- types.ResponseSetOption{retCode}
|
||||
logstr := app.SetOption(req.Key, req.Value)
|
||||
responses <- types.ResponseSetOption{logstr}
|
||||
case types.RequestAppendTx:
|
||||
events, retCode := app.AppendTx(req.TxBytes)
|
||||
responses <- types.ResponseAppendTx{retCode}
|
||||
for _, event := range events {
|
||||
responses <- types.ResponseEvent{event}
|
||||
}
|
||||
code, result, logstr := app.AppendTx(req.TxBytes)
|
||||
responses <- types.ResponseAppendTx{code, result, logstr}
|
||||
case types.RequestCheckTx:
|
||||
retCode := app.CheckTx(req.TxBytes)
|
||||
responses <- types.ResponseCheckTx{retCode}
|
||||
code, result, logstr := app.CheckTx(req.TxBytes)
|
||||
responses <- types.ResponseCheckTx{code, result, logstr}
|
||||
case types.RequestGetHash:
|
||||
hash, retCode := app.GetHash()
|
||||
responses <- types.ResponseGetHash{retCode, hash}
|
||||
case types.RequestAddListener:
|
||||
retCode := app.AddListener(req.EventKey)
|
||||
responses <- types.ResponseAddListener{retCode}
|
||||
case types.RequestRemListener:
|
||||
retCode := app.RemListener(req.EventKey)
|
||||
responses <- types.ResponseRemListener{retCode}
|
||||
hash, logstr := app.GetHash()
|
||||
responses <- types.ResponseGetHash{hash, logstr}
|
||||
case types.RequestQuery:
|
||||
result, retCode := app.Query(req.QueryBytes)
|
||||
responses <- types.ResponseQuery{retCode, result}
|
||||
result, logstr := app.Query(req.QueryBytes)
|
||||
responses <- types.ResponseQuery{result, logstr}
|
||||
default:
|
||||
responses <- types.ResponseException{"Unknown request"}
|
||||
}
|
||||
|
|
|
@ -8,10 +8,11 @@ bash tests/test_dummy.sh
|
|||
# test golang counter
|
||||
bash tests/test_counter.sh
|
||||
|
||||
# test js counter
|
||||
cd example/js
|
||||
COUNTER_APP="node app.js" bash $ROOT/tests/test_counter.sh
|
||||
|
||||
# test python counter
|
||||
cd example/python
|
||||
cd ../python
|
||||
COUNTER_APP="python app.py" bash $ROOT/tests/test_counter.sh
|
||||
|
||||
# test js counter
|
||||
cd ../js
|
||||
COUNTER_APP="node app.js" bash $ROOT/tests/test_counter.sh
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
#! /bin/bash
|
||||
function finish {
|
||||
echo "Cleaning up..."
|
||||
ps -p $PID > /dev/null
|
||||
if [[ "$?" == "0" ]]; then
|
||||
kill -9 $PID
|
||||
fi
|
||||
}
|
||||
trap finish EXIT
|
||||
|
||||
# so we can test other languages
|
||||
if [[ "$COUNTER_APP" == "" ]]; then
|
||||
|
@ -55,21 +64,15 @@ fi
|
|||
HASH1=`echo "$OUTPUT" | tail -n +3 | head -n 1`
|
||||
HASH2=`echo "$OUTPUT" | tail -n +5 | head -n 1`
|
||||
|
||||
if [[ "${HASH1:0:2}" != "01" ]]; then
|
||||
if [[ "${HASH1: -2}" != "01" ]]; then
|
||||
echo "Expected hash to lead with 01. Got $HASH1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${HASH2:0:2}" != "02" ]]; then
|
||||
if [[ "${HASH2: -2}" != "02" ]]; then
|
||||
echo "Expected hash to lead with 02. Got $HASH2"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "... Pass!"
|
||||
echo ""
|
||||
|
||||
ps -p $PID > /dev/null
|
||||
if [[ "$?" == "0" ]]; then
|
||||
kill -9 $PID
|
||||
fi
|
||||
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
#! /bin/bash
|
||||
function finish {
|
||||
echo "Cleaning up..."
|
||||
ps -p $PID > /dev/null
|
||||
if [[ "$?" == "0" ]]; then
|
||||
kill -9 $PID
|
||||
fi
|
||||
}
|
||||
trap finish EXIT
|
||||
|
||||
# Make sure the tmsp cli can connect to the dummy
|
||||
echo "Dummy test ..."
|
||||
|
@ -51,7 +59,3 @@ if [[ "$HASH1" != "$RESULT_HASH" ]]; then
|
|||
fi
|
||||
echo "... Pass!"
|
||||
echo ""
|
||||
|
||||
|
||||
kill $PID
|
||||
sleep 1
|
||||
|
|
|
@ -2,30 +2,21 @@ package types
|
|||
|
||||
type Application interface {
|
||||
|
||||
// Echo a message
|
||||
Echo(message string) string
|
||||
|
||||
// Return application info
|
||||
Info() []string
|
||||
Info() (info string)
|
||||
|
||||
// Set application option (e.g. mode=mempool, mode=consensus)
|
||||
SetOption(key string, value string) RetCode
|
||||
SetOption(key string, value string) (log string)
|
||||
|
||||
// Append a tx
|
||||
AppendTx(tx []byte) ([]Event, RetCode)
|
||||
AppendTx(tx []byte) (code RetCode, result []byte, log string)
|
||||
|
||||
// Validate a tx for the mempool
|
||||
CheckTx(tx []byte) RetCode
|
||||
CheckTx(tx []byte) (code RetCode, result []byte, log string)
|
||||
|
||||
// Return the application Merkle root hash
|
||||
GetHash() ([]byte, RetCode)
|
||||
|
||||
// Add event listener
|
||||
AddListener(key string) RetCode
|
||||
|
||||
// Remove event listener
|
||||
RemListener(key string) RetCode
|
||||
GetHash() (hash []byte, log string)
|
||||
|
||||
// Query for state
|
||||
Query(query []byte) ([]byte, RetCode)
|
||||
Query(query []byte) (result []byte, log string)
|
||||
}
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
package types
|
||||
|
||||
type Event struct {
|
||||
Key string
|
||||
Data []byte
|
||||
}
|
|
@ -86,11 +86,6 @@ var _ = wire.RegisterInterface(
|
|||
|
||||
//----------------------------------------
|
||||
|
||||
type KVPair struct {
|
||||
Key []byte
|
||||
Value []byte
|
||||
}
|
||||
|
||||
type ResponseException struct {
|
||||
Error string
|
||||
}
|
||||
|
@ -103,32 +98,33 @@ type ResponseFlush struct {
|
|||
}
|
||||
|
||||
type ResponseInfo struct {
|
||||
Data []string
|
||||
Info string
|
||||
}
|
||||
|
||||
type ResponseSetOption struct {
|
||||
Error string
|
||||
Log string
|
||||
}
|
||||
|
||||
type ResponseAppendTx struct {
|
||||
RetCode
|
||||
RetData []KVPair
|
||||
Error string
|
||||
Code RetCode
|
||||
Result []byte
|
||||
Log string
|
||||
}
|
||||
|
||||
type ResponseCheckTx struct {
|
||||
RetCode
|
||||
RetData []KVPair
|
||||
Error string
|
||||
Code RetCode
|
||||
Result []byte
|
||||
Log string
|
||||
}
|
||||
|
||||
type ResponseGetHash struct {
|
||||
Hash []byte
|
||||
Log string
|
||||
}
|
||||
|
||||
type ResponseQuery struct {
|
||||
Result []byte
|
||||
Error string
|
||||
Log string
|
||||
}
|
||||
|
||||
type Response interface {
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
type RetCode int
|
||||
|
||||
// Reserved return codes
|
||||
|
@ -17,15 +13,6 @@ const (
|
|||
RetCodeBadNonce RetCode = 6
|
||||
)
|
||||
|
||||
func (r RetCode) Error() error {
|
||||
switch r {
|
||||
case RetCodeOK:
|
||||
return nil
|
||||
default:
|
||||
return errors.New(r.String())
|
||||
}
|
||||
}
|
||||
|
||||
//go:generate stringer -type=RetCode
|
||||
|
||||
// NOTE: The previous comment generates r.String().
|
||||
|
|
|
@ -4,9 +4,9 @@ package types
|
|||
|
||||
import "fmt"
|
||||
|
||||
const _RetCode_name = "RetCodeOKRetCodeInternalErrorRetCodeUnauthorizedRetCodeInsufficientFeesRetCodeUnknownRequestRetCodeEncodingErrorRetCodeInvalidNonce"
|
||||
const _RetCode_name = "RetCodeOKRetCodeInternalErrorRetCodeUnauthorizedRetCodeInsufficientFeesRetCodeUnknownRequestRetCodeEncodingErrorRetCodeBadNonce"
|
||||
|
||||
var _RetCode_index = [...]uint8{0, 9, 29, 48, 71, 92, 112, 131}
|
||||
var _RetCode_index = [...]uint8{0, 9, 29, 48, 71, 92, 112, 127}
|
||||
|
||||
func (i RetCode) String() string {
|
||||
if i < 0 || i >= RetCode(len(_RetCode_index)-1) {
|
||||
|
|
Loading…
Reference in New Issue