Relaxed nonce-checking for demo
This commit is contained in:
parent
7dccf61484
commit
538f3110b1
5
Makefile
5
Makefile
|
@ -1,9 +1,6 @@
|
||||||
.PHONY: all test get_deps
|
.PHONY: all test get_deps
|
||||||
|
|
||||||
all: protoc test install
|
all: test install
|
||||||
|
|
||||||
protoc:
|
|
||||||
protoc --go_out=. types/*.proto
|
|
||||||
|
|
||||||
install: get_deps
|
install: get_deps
|
||||||
go install github.com/tendermint/blackstar/cmd/...
|
go install github.com/tendermint/blackstar/cmd/...
|
||||||
|
|
21
app/app.go
21
app/app.go
|
@ -1,6 +1,7 @@
|
||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/tendermint/blackstar/types"
|
"github.com/tendermint/blackstar/types"
|
||||||
"github.com/tendermint/go-crypto"
|
"github.com/tendermint/go-crypto"
|
||||||
"github.com/tendermint/go-wire"
|
"github.com/tendermint/go-wire"
|
||||||
|
@ -62,7 +63,7 @@ func (app *Blackstar) AppendTx(txBytes []byte) (code tmsp.CodeType, result []byt
|
||||||
// Load accounts
|
// Load accounts
|
||||||
accMap := loadAccounts(app.eyesCli, allPubKeys(tx))
|
accMap := loadAccounts(app.eyesCli, allPubKeys(tx))
|
||||||
// Execute tx
|
// Execute tx
|
||||||
accs, code, errStr := execTx(tx, accMap)
|
accs, code, errStr := execTx(tx, accMap, false)
|
||||||
if errStr != "" {
|
if errStr != "" {
|
||||||
return code, nil, "Error executing tx: " + errStr
|
return code, nil, "Error executing tx: " + errStr
|
||||||
}
|
}
|
||||||
|
@ -89,7 +90,7 @@ func (app *Blackstar) CheckTx(txBytes []byte) (code tmsp.CodeType, result []byte
|
||||||
// Load accounts
|
// Load accounts
|
||||||
accMap := loadAccounts(app.eyesCli, allPubKeys(tx))
|
accMap := loadAccounts(app.eyesCli, allPubKeys(tx))
|
||||||
// Execute tx
|
// Execute tx
|
||||||
_, code, errStr = execTx(tx, accMap)
|
_, code, errStr = execTx(tx, accMap, false)
|
||||||
if errStr != "" {
|
if errStr != "" {
|
||||||
return code, nil, "Error (mock) executing tx: " + errStr
|
return code, nil, "Error (mock) executing tx: " + errStr
|
||||||
}
|
}
|
||||||
|
@ -225,7 +226,9 @@ func allPubKeys(tx types.Tx) (pubKeys []crypto.PubKey) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns accounts in order of types.Tx inputs and outputs
|
// Returns accounts in order of types.Tx inputs and outputs
|
||||||
func execTx(tx types.Tx, accMap map[string]types.PubAccount) (accs []types.PubAccount, code tmsp.CodeType, errStr string) {
|
// appendTx: true if this is for AppendTx.
|
||||||
|
// TODO: create more intelligent sequence-checking. Current impl is just for a throughput demo.
|
||||||
|
func execTx(tx types.Tx, accMap map[string]types.PubAccount, appendTx bool) (accs []types.PubAccount, code tmsp.CodeType, errStr string) {
|
||||||
accs = make([]types.PubAccount, 0, len(tx.Inputs)+len(tx.Outputs))
|
accs = make([]types.PubAccount, 0, len(tx.Inputs)+len(tx.Outputs))
|
||||||
// Deduct from inputs
|
// Deduct from inputs
|
||||||
for _, input := range tx.Inputs {
|
for _, input := range tx.Inputs {
|
||||||
|
@ -233,9 +236,15 @@ func execTx(tx types.Tx, accMap map[string]types.PubAccount) (accs []types.PubAc
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, tmsp.CodeType_UnknownAccount, "Input account does not exist"
|
return nil, tmsp.CodeType_UnknownAccount, "Input account does not exist"
|
||||||
}
|
}
|
||||||
|
if appendTx {
|
||||||
if acc.Sequence != input.Sequence {
|
if acc.Sequence != input.Sequence {
|
||||||
return nil, tmsp.CodeType_BadNonce, "Invalid sequence"
|
return nil, tmsp.CodeType_BadNonce, "Invalid sequence"
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if acc.Sequence > input.Sequence {
|
||||||
|
return nil, tmsp.CodeType_BadNonce, "Invalid sequence (too low)"
|
||||||
|
}
|
||||||
|
}
|
||||||
if acc.Balance < input.Amount {
|
if acc.Balance < input.Amount {
|
||||||
return nil, tmsp.CodeType_InsufficientFunds, "Insufficient funds"
|
return nil, tmsp.CodeType_InsufficientFunds, "Insufficient funds"
|
||||||
}
|
}
|
||||||
|
@ -256,8 +265,8 @@ func execTx(tx types.Tx, accMap map[string]types.PubAccount) (accs []types.PubAc
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
accMap[output.PubKey.KeyString()] = acc
|
accMap[output.PubKey.KeyString()] = acc
|
||||||
continue
|
accs = append(accs, acc)
|
||||||
}
|
} else {
|
||||||
// Good!
|
// Good!
|
||||||
if (acc.Balance + output.Amount) < acc.Balance {
|
if (acc.Balance + output.Amount) < acc.Balance {
|
||||||
return nil, tmsp.CodeType_InternalError, "Output balance overflow in execTx"
|
return nil, tmsp.CodeType_InternalError, "Output balance overflow in execTx"
|
||||||
|
@ -265,6 +274,7 @@ func execTx(tx types.Tx, accMap map[string]types.PubAccount) (accs []types.PubAc
|
||||||
acc.Balance += output.Amount
|
acc.Balance += output.Amount
|
||||||
accs = append(accs, acc)
|
accs = append(accs, acc)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return accs, tmsp.CodeType_OK, ""
|
return accs, tmsp.CodeType_OK, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,6 +306,7 @@ func loadAccounts(eyesCli *eyes.MerkleEyesClient, pubKeys []crypto.PubKey) (accM
|
||||||
|
|
||||||
// NOTE: accs must be stored in deterministic order.
|
// NOTE: accs must be stored in deterministic order.
|
||||||
func storeAccounts(eyesCli *eyes.MerkleEyesClient, accs []types.PubAccount) {
|
func storeAccounts(eyesCli *eyes.MerkleEyesClient, accs []types.PubAccount) {
|
||||||
|
fmt.Println("STORE ACCOUNTS", accs)
|
||||||
for _, acc := range accs {
|
for _, acc := range accs {
|
||||||
accBytes := wire.BinaryBytes(acc.Account)
|
accBytes := wire.BinaryBytes(acc.Account)
|
||||||
err := eyesCli.SetSync([]byte(acc.PubKey.KeyString()), accBytes)
|
err := eyesCli.SetSync([]byte(acc.PubKey.KeyString()), accBytes)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
|
@ -38,6 +37,7 @@ func main() {
|
||||||
sequence := uint(0)
|
sequence := uint(0)
|
||||||
// Make a bunch of PrivAccounts
|
// Make a bunch of PrivAccounts
|
||||||
privAccounts := tests.RandAccounts(1000, 1000000, 0)
|
privAccounts := tests.RandAccounts(1000, 1000000, 0)
|
||||||
|
privAccountSequences := make(map[string]int)
|
||||||
|
|
||||||
// Send coins to each account
|
// Send coins to each account
|
||||||
for i := 0; i < len(privAccounts); i++ {
|
for i := 0; i < len(privAccounts); i++ {
|
||||||
|
@ -76,25 +76,51 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Now send coins between these accounts
|
||||||
// Make a bunch of requests
|
for {
|
||||||
for i := 0; ; i++ {
|
randA := RandInt() % len(privAccounts)
|
||||||
binary.BigEndian.PutUint64(buf, uint64(i))
|
randB := RandInt() % len(privAccounts)
|
||||||
//txBytes := hex.EncodeToString(buf[:n])
|
if randA == randB {
|
||||||
request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx", Arr(buf[:8]))
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
privAccountA := privAccounts[randA]
|
||||||
|
privAccountASequence := privAccountSequences[privAccountA.PubKey.KeyString()]
|
||||||
|
privAccountSequences[privAccountA.PubKey.KeyString()] = privAccountASequence + 1
|
||||||
|
privAccountB := privAccounts[randB]
|
||||||
|
|
||||||
|
tx := types.Tx{
|
||||||
|
Inputs: []types.Input{
|
||||||
|
types.Input{
|
||||||
|
PubKey: privAccountA.PubKey,
|
||||||
|
Amount: 3,
|
||||||
|
Sequence: uint(privAccountASequence),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outputs: []types.Output{
|
||||||
|
types.Output{
|
||||||
|
PubKey: privAccountB.PubKey,
|
||||||
|
Amount: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign request
|
||||||
|
signBytes := wire.BinaryBytes(tx)
|
||||||
|
sig := privAccountA.PrivKey.Sign(signBytes)
|
||||||
|
tx.Inputs[0].Signature = sig
|
||||||
|
//fmt.Println("tx:", tx)
|
||||||
|
|
||||||
|
// Write request
|
||||||
|
txBytes := wire.BinaryBytes(tx)
|
||||||
|
request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", Arr(txBytes))
|
||||||
reqBytes := wire.JSONBytes(request)
|
reqBytes := wire.JSONBytes(request)
|
||||||
//fmt.Println("!!", string(reqBytes))
|
//fmt.Print(".")
|
||||||
fmt.Print(".")
|
|
||||||
err := ws.WriteMessage(websocket.TextMessage, reqBytes)
|
err := ws.WriteMessage(websocket.TextMessage, reqBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Exit(err.Error())
|
Exit("writing websocket request: " + err.Error())
|
||||||
}
|
}
|
||||||
if i%1000 == 0 {
|
|
||||||
fmt.Println(i)
|
|
||||||
}
|
}
|
||||||
time.Sleep(time.Microsecond * 1000)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
ws.Stop()
|
ws.Stop()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue