Added genesis file; Added draft of Tendermint tests
This commit is contained in:
parent
d31a8d8258
commit
436e0ba7d7
|
@ -1,4 +1,4 @@
|
||||||
package blackstar
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/tendermint/blackstar/types"
|
"github.com/tendermint/blackstar/types"
|
||||||
|
@ -25,18 +25,13 @@ func (app *Blackstar) Info() string {
|
||||||
return "Blackstar v" + version
|
return "Blackstar v" + version
|
||||||
}
|
}
|
||||||
|
|
||||||
type SetAccount struct {
|
|
||||||
PubKey crypto.PubKey
|
|
||||||
Account types.Account
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *Blackstar) SetOption(key string, value string) (log string) {
|
func (app *Blackstar) SetOption(key string, value string) (log string) {
|
||||||
if key == "setAccount" {
|
if key == "setAccount" {
|
||||||
var err error
|
var err error
|
||||||
var setAccount SetAccount
|
var setAccount types.PubAccount
|
||||||
wire.ReadJSONPtr(&setAccount, []byte(value), &err)
|
wire.ReadJSONPtr(&setAccount, []byte(value), &err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "Error decoding SetAccount message: " + err.Error()
|
return "Error decoding setAccount message: " + err.Error()
|
||||||
}
|
}
|
||||||
pubKeyBytes := wire.BinaryBytes(setAccount.PubKey)
|
pubKeyBytes := wire.BinaryBytes(setAccount.PubKey)
|
||||||
accBytes := wire.BinaryBytes(setAccount.Account)
|
accBytes := wire.BinaryBytes(setAccount.Account)
|
||||||
|
@ -225,8 +220,8 @@ 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.Account) (accs []types.Account, code tmsp.CodeType, errStr string) {
|
func execTx(tx types.Tx, accMap map[string]types.PubAccount) (accs []types.PubAccount, code tmsp.CodeType, errStr string) {
|
||||||
accs = make([]types.Account, 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 {
|
||||||
var acc, ok = accMap[input.PubKey.KeyString()]
|
var acc, ok = accMap[input.PubKey.KeyString()]
|
||||||
|
@ -249,9 +244,11 @@ func execTx(tx types.Tx, accMap map[string]types.Account) (accs []types.Account,
|
||||||
var acc, ok = accMap[output.PubKey.KeyString()]
|
var acc, ok = accMap[output.PubKey.KeyString()]
|
||||||
if !ok {
|
if !ok {
|
||||||
// Create new account if it doesn't already exist.
|
// Create new account if it doesn't already exist.
|
||||||
acc = types.Account{
|
acc = types.PubAccount{
|
||||||
PubKey: output.PubKey,
|
PubKey: output.PubKey,
|
||||||
|
Account: types.Account{
|
||||||
Balance: output.Amount,
|
Balance: output.Amount,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
accMap[output.PubKey.KeyString()] = acc
|
accMap[output.PubKey.KeyString()] = acc
|
||||||
continue
|
continue
|
||||||
|
@ -268,9 +265,34 @@ func execTx(tx types.Tx, accMap map[string]types.Account) (accs []types.Account,
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
func loadAccounts(eyesCli *eyes.MerkleEyesClient, pubKeys []crypto.PubKey) map[string]types.Account {
|
func loadAccounts(eyesCli *eyes.MerkleEyesClient, pubKeys []crypto.PubKey) (accMap map[string]types.PubAccount) {
|
||||||
return nil
|
accMap = make(map[string]types.PubAccount, len(pubKeys))
|
||||||
|
for _, pubKey := range pubKeys {
|
||||||
|
keyString := pubKey.KeyString()
|
||||||
|
accBytes, err := eyesCli.GetSync([]byte(keyString))
|
||||||
|
if err != nil {
|
||||||
|
panic("Error loading account: " + err.Error())
|
||||||
|
}
|
||||||
|
var acc types.PubAccount
|
||||||
|
err = wire.ReadBinaryBytes(accBytes, &acc)
|
||||||
|
if err != nil {
|
||||||
|
panic("Error reading account: " + err.Error())
|
||||||
|
}
|
||||||
|
acc.PubKey = pubKey // Set volatile field
|
||||||
|
accMap[keyString] = acc
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func storeAccounts(eyesCli *eyes.MerkleEyesClient, accs []types.Account) {
|
// NOTE: accs must be stored in deterministic order.
|
||||||
|
func storeAccounts(eyesCli *eyes.MerkleEyesClient, accs []types.PubAccount) {
|
||||||
|
for _, acc := range accs {
|
||||||
|
accBytes := wire.BinaryBytes(acc.Account)
|
||||||
|
err := eyesCli.SetSync([]byte(acc.PubKey.KeyString()), accBytes)
|
||||||
|
if err != nil {
|
||||||
|
panic("Error storing account: " + err.Error())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------
|
|
@ -0,0 +1,6 @@
|
||||||
|
{"Accounts":[
|
||||||
|
{
|
||||||
|
"PubKey":[1,"31F4BF201D3606E33707B098B1EEA7D03A4BB9E9795F0116ED1A038D7B5A6BDE"],
|
||||||
|
"Account":{"Sequence":0,"Balance":2100000000000000}
|
||||||
|
}
|
||||||
|
]}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/tendermint/blackstar/app"
|
||||||
|
"github.com/tendermint/blackstar/types"
|
||||||
|
. "github.com/tendermint/go-common"
|
||||||
|
"github.com/tendermint/go-wire"
|
||||||
|
eyes "github.com/tendermint/merkleeyes/client"
|
||||||
|
"github.com/tendermint/tmsp/server"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
addrPtr := flag.String("address", "tcp://0.0.0.0:46658", "Listen address")
|
||||||
|
eyesPtr := flag.String("eyes", "tcp://0.0.0.0:46659", "MerkleEyes address")
|
||||||
|
genPtr := flag.String("genesis", "genesis.json", "Genesis JSON file")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
// Connect to MerkleEyes
|
||||||
|
eyesCli, err := eyes.NewMerkleEyesClient(*eyesPtr)
|
||||||
|
if err != nil {
|
||||||
|
Exit("connect to MerkleEyes: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create BlackStar app
|
||||||
|
app := app.NewBlackstar(eyesCli)
|
||||||
|
|
||||||
|
// Load GenesisState
|
||||||
|
jsonBytes, err := ReadFile(*genPtr)
|
||||||
|
if err != nil {
|
||||||
|
Exit("read genesis: " + err.Error())
|
||||||
|
}
|
||||||
|
genesisState := types.GenesisState{}
|
||||||
|
wire.ReadJSONPtr(&genesisState, jsonBytes, &err)
|
||||||
|
if err != nil {
|
||||||
|
Exit("parsing genesis JSON: " + err.Error())
|
||||||
|
}
|
||||||
|
for _, account := range genesisState.Accounts {
|
||||||
|
pubKeyBytes := wire.BinaryBytes(account.PubKey)
|
||||||
|
accBytes := wire.BinaryBytes(account.Account)
|
||||||
|
err = eyesCli.SetSync(pubKeyBytes, accBytes)
|
||||||
|
if err != nil {
|
||||||
|
Exit("loading genesis accounts: " + err.Error())
|
||||||
|
}
|
||||||
|
fmt.Println("Loaded ", account)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the listener
|
||||||
|
_, err = server.StartListener(*addrPtr, app)
|
||||||
|
if err != nil {
|
||||||
|
Exit("create listener: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait forever
|
||||||
|
TrapSignal(func() {
|
||||||
|
// Cleanup
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/tendermint/blackstar/types"
|
||||||
|
. "github.com/tendermint/go-common"
|
||||||
|
"github.com/tendermint/go-crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Creates a PrivAccount from secret.
|
||||||
|
// The amount is not set.
|
||||||
|
func PrivAccountFromSecret(secret string) types.PrivAccount {
|
||||||
|
privKey := crypto.GenPrivKeyEd25519FromSecret(secret)
|
||||||
|
privAccount := types.PrivAccount{
|
||||||
|
PrivKey: privKey,
|
||||||
|
PubKey: privKey.PubKey(),
|
||||||
|
Account: types.Account{
|
||||||
|
Sequence: 0,
|
||||||
|
Balance: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return privAccount
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make `num` random accounts
|
||||||
|
func RandAccounts(num int, minAmount uint64, maxAmount uint64) []types.PrivAccount {
|
||||||
|
privAccs := make([]types.PrivAccount, num)
|
||||||
|
for i := 0; i < num; i++ {
|
||||||
|
|
||||||
|
balance := minAmount
|
||||||
|
if maxAmount > minAmount {
|
||||||
|
balance += RandUint64() % (maxAmount - minAmount)
|
||||||
|
}
|
||||||
|
|
||||||
|
privKey := crypto.GenPrivKeyEd25519()
|
||||||
|
pubKey := privKey.PubKey()
|
||||||
|
privAccs[i] = types.PrivAccount{
|
||||||
|
PrivKey: privKey,
|
||||||
|
PubKey: pubKey,
|
||||||
|
Account: types.Account{
|
||||||
|
Sequence: 0,
|
||||||
|
Balance: balance,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return privAccs
|
||||||
|
}
|
Binary file not shown.
|
@ -0,0 +1,96 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
"github.com/tendermint/blackstar/tests"
|
||||||
|
"github.com/tendermint/blackstar/types"
|
||||||
|
. "github.com/tendermint/go-common"
|
||||||
|
"github.com/tendermint/go-rpc/client"
|
||||||
|
"github.com/tendermint/go-rpc/types"
|
||||||
|
"github.com/tendermint/go-wire"
|
||||||
|
_ "github.com/tendermint/tendermint/rpc/core/types" // Register RPCResponse > Result types
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ws := rpcclient.NewWSClient("ws://127.0.0.1:46657/websocket")
|
||||||
|
// ws := rpcclient.NewWSClient("ws://104.236.69.128:46657/websocket")
|
||||||
|
_, err := ws.Start()
|
||||||
|
if err != nil {
|
||||||
|
Exit(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read a bunch of responses
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
res, ok := <-ws.ResultsCh
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
fmt.Println("res:", Blue(string(res)))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Get the root account
|
||||||
|
root := tests.PrivAccountFromSecret("root")
|
||||||
|
sequence := uint(0)
|
||||||
|
// Make a bunch of PrivAccounts
|
||||||
|
privAccounts := tests.RandAccounts(1000, 1000000, 0)
|
||||||
|
|
||||||
|
// Send coins to each account
|
||||||
|
for i := 0; i < len(privAccounts); i++ {
|
||||||
|
privAccount := privAccounts[i]
|
||||||
|
tx := types.Tx{
|
||||||
|
Inputs: []types.Input{
|
||||||
|
types.Input{
|
||||||
|
PubKey: root.PubKey,
|
||||||
|
Amount: 1000002,
|
||||||
|
Sequence: sequence,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outputs: []types.Output{
|
||||||
|
types.Output{
|
||||||
|
PubKey: privAccount.PubKey,
|
||||||
|
Amount: 1000000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
sequence += 1
|
||||||
|
|
||||||
|
// Write request
|
||||||
|
txBytes := wire.BinaryBytes(tx)
|
||||||
|
fmt.Println("tx:", hex.EncodeToString(txBytes))
|
||||||
|
request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx", Arr(txBytes))
|
||||||
|
reqBytes := wire.JSONBytes(request)
|
||||||
|
fmt.Println("req:", hex.EncodeToString(reqBytes))
|
||||||
|
//fmt.Print(".")
|
||||||
|
err := ws.WriteMessage(websocket.TextMessage, reqBytes)
|
||||||
|
if err != nil {
|
||||||
|
Exit("writing websocket request: " + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Make a bunch of requests
|
||||||
|
for i := 0; ; i++ {
|
||||||
|
binary.BigEndian.PutUint64(buf, uint64(i))
|
||||||
|
//txBytes := hex.EncodeToString(buf[:n])
|
||||||
|
request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx", Arr(buf[:8]))
|
||||||
|
reqBytes := wire.JSONBytes(request)
|
||||||
|
//fmt.Println("!!", string(reqBytes))
|
||||||
|
fmt.Print(".")
|
||||||
|
err := ws.WriteMessage(websocket.TextMessage, reqBytes)
|
||||||
|
if err != nil {
|
||||||
|
Exit(err.Error())
|
||||||
|
}
|
||||||
|
if i%1000 == 0 {
|
||||||
|
fmt.Println(i)
|
||||||
|
}
|
||||||
|
time.Sleep(time.Microsecond * 1000)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
ws.Stop()
|
||||||
|
}
|
|
@ -24,7 +24,19 @@ type Output struct {
|
||||||
type Account struct {
|
type Account struct {
|
||||||
Sequence uint
|
Sequence uint
|
||||||
Balance uint64
|
Balance uint64
|
||||||
|
}
|
||||||
// For convenience
|
|
||||||
crypto.PubKey `json:"-"`
|
type PubAccount struct {
|
||||||
|
crypto.PubKey
|
||||||
|
Account
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrivAccount struct {
|
||||||
|
crypto.PubKey
|
||||||
|
crypto.PrivKey
|
||||||
|
Account
|
||||||
|
}
|
||||||
|
|
||||||
|
type GenesisState struct {
|
||||||
|
Accounts []PubAccount
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue