From 436e0ba7d702f8b31bfa0ec90840cf06a1e7d518 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 7 Feb 2016 22:54:49 -0800 Subject: [PATCH] Added genesis file; Added draft of Tendermint tests --- blackstar.go => app/app.go | 54 +++++++++++++------ genesis.json | 6 +++ main.go | 62 ++++++++++++++++++++++ tests/common.go | 47 +++++++++++++++++ tests/tendermint/.main.go.swp | Bin 0 -> 12288 bytes tests/tendermint/main.go | 96 ++++++++++++++++++++++++++++++++++ types/types.go | 18 +++++-- 7 files changed, 264 insertions(+), 19 deletions(-) rename blackstar.go => app/app.go (84%) create mode 100644 genesis.json create mode 100644 main.go create mode 100644 tests/common.go create mode 100644 tests/tendermint/.main.go.swp create mode 100644 tests/tendermint/main.go diff --git a/blackstar.go b/app/app.go similarity index 84% rename from blackstar.go rename to app/app.go index f7183cfdc..2e23dc37b 100644 --- a/blackstar.go +++ b/app/app.go @@ -1,4 +1,4 @@ -package blackstar +package app import ( "github.com/tendermint/blackstar/types" @@ -25,18 +25,13 @@ func (app *Blackstar) Info() string { return "Blackstar v" + version } -type SetAccount struct { - PubKey crypto.PubKey - Account types.Account -} - func (app *Blackstar) SetOption(key string, value string) (log string) { if key == "setAccount" { var err error - var setAccount SetAccount + var setAccount types.PubAccount wire.ReadJSONPtr(&setAccount, []byte(value), &err) if err != nil { - return "Error decoding SetAccount message: " + err.Error() + return "Error decoding setAccount message: " + err.Error() } pubKeyBytes := wire.BinaryBytes(setAccount.PubKey) 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 -func execTx(tx types.Tx, accMap map[string]types.Account) (accs []types.Account, code tmsp.CodeType, errStr string) { - accs = make([]types.Account, 0, len(tx.Inputs)+len(tx.Outputs)) +func execTx(tx types.Tx, accMap map[string]types.PubAccount) (accs []types.PubAccount, code tmsp.CodeType, errStr string) { + accs = make([]types.PubAccount, 0, len(tx.Inputs)+len(tx.Outputs)) // Deduct from inputs for _, input := range tx.Inputs { 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()] if !ok { // Create new account if it doesn't already exist. - acc = types.Account{ - PubKey: output.PubKey, - Balance: output.Amount, + acc = types.PubAccount{ + PubKey: output.PubKey, + Account: types.Account{ + Balance: output.Amount, + }, } accMap[output.PubKey.KeyString()] = acc 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 { - return nil +func loadAccounts(eyesCli *eyes.MerkleEyesClient, pubKeys []crypto.PubKey) (accMap map[string]types.PubAccount) { + 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()) + } + } } + +//---------------------------------------- diff --git a/genesis.json b/genesis.json new file mode 100644 index 000000000..a810af0a7 --- /dev/null +++ b/genesis.json @@ -0,0 +1,6 @@ +{"Accounts":[ + { + "PubKey":[1,"31F4BF201D3606E33707B098B1EEA7D03A4BB9E9795F0116ED1A038D7B5A6BDE"], + "Account":{"Sequence":0,"Balance":2100000000000000} + } +]} diff --git a/main.go b/main.go new file mode 100644 index 000000000..ffd1c50df --- /dev/null +++ b/main.go @@ -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 + }) + +} diff --git a/tests/common.go b/tests/common.go new file mode 100644 index 000000000..d231538fd --- /dev/null +++ b/tests/common.go @@ -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 +} diff --git a/tests/tendermint/.main.go.swp b/tests/tendermint/.main.go.swp new file mode 100644 index 0000000000000000000000000000000000000000..1ced6506665a950e8d59fa760e592ad81e5c9790 GIT binary patch literal 12288 zcmeI2?`s@I7{{l@RvyN9O2WZx6xeX+o}T`~2kB*TT&oK2FG+0n@$r{2UFK9GMHk8P01X z^MZSI9tQQbkG%(new&M$Yz86or3n3Mq*hubFXRnhvAE1cBZ`$@ss~|Bsz9JqDw)33 z2%^}l^0m%wk5#}bu(1LyRT-JwPWFtA=C#qw&Jf+T^TfvX_KsD+Dqt0`3RnfK0#*U5 zfK|XM@V`?)H8+v-nAPU)%+7YdHw}DuoA%2pU=^?mSOu&CRspMkRlq7>6|f3e1*`&A zfrn6mpiIch7D66*6v5;F|7W{%_~R);eh0sTo8TL816%-o0uHL+C^!Jdfe*HTP2koOg!~PD0-u4);5;}2UI$t556&t4 z0Iq|p;A3zBG{7R51Bbydcpm(<4gSFQ;9GD5da2Zs^|`VcNA z8?sfvDqt1(PbqMYWZKdzD&BOngk*O6B$Gj3CZnPT^NMxG?rqU@jqzL*3NBg5<1*b% zNAvl7Ry#7@GL?q%<^_(g)nhj@{ZWNRuV^beHAVCEo!hpvok+P%2ya#hF5GO-99?v1 zipEhrvDWRv6h-`}M5NdplQO6>x6MkDhc%|WMb=T>-W(O|t(jGvm^0q`;kb_Hm>%En z_aQ`QXvoP?sSt71?LTP@do43`B$#)!c>I|0tPNW@lGiiS*V;-nL$%su(mTf53-bpT z5-ZoK1T_|wF^*FbJSc~ORLiP^_OuXgsZ}{sm|RLG@B6A_hS2U-SjU@IUa4CudvFgo4)!Dcl1+h2ZQYRq%#JKjEqpjpRGM+13&`3MY@1y%@G(2pS^?f>r z*l0jYtvFnvyrR|9(~%_O@5VaONi~TzxpLajA4<`_^ga6mb?7i1$R#pAkje+oWGZdF zRNj$C#9e@*>u82M$$HSL^%{3iYFC5@&S^J^iSnrp;i%3AL8hNbErGUPcQYo@$;wk5 zJqzT`?1Y~BNK{7Z#Kj?_!&7v$m$h>_Tp@$WS7y4wTd^vbJ&O(5?VWFx-e9W*+7!{- z(_yGhu$FXRVvwxq<1N)}DYJW%OIe_2me$-G7_r!msz7`34TM6w!Hf+AL#g0=y*Q4< zy)evGDvJIc)zO(tLR;+UkW*9Bw^B`cCR!qy^!AA8ep+X-n>Nb!_Y9;j;)pH{c@#^k zIAsAgPLRlkJfxp8QRvO&Ed+77E3I^OEzI?EKy~$8XCuzv&IUGPPd)8YZ){gTr4_n8 zM(Tk>f;WmR6im5}Hqw<3LmXy`sugCGO@(|8Z-nkHAJ|e-uhyA*i@E&@DYHqXN~(QH zu%M=w7`FNluO;PLFqxxhAk_UMDB255w(3eAT!En$8VRX#T0zBev$}!E7FbZevkJ*3 zk0q1c612{nVoh;b&Y5b1QO%1k5K7Mr&f8Llg5n(3BZjq&>U^qr&|JGtTNZqOG(YZ* z?V0cInGTObY5-s7(+h`^j z4+q*CJl=T3)CqU}-n=hEy`KgQt6W6&dXUN(mW_k8tnE+}c^U64AFl?7M2#jFin{nS N9f#}jTZBmq`4{$bFWmqD literal 0 HcmV?d00001 diff --git a/tests/tendermint/main.go b/tests/tendermint/main.go new file mode 100644 index 000000000..34cc2f45e --- /dev/null +++ b/tests/tendermint/main.go @@ -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() +} diff --git a/types/types.go b/types/types.go index 1011a550d..15d04b745 100644 --- a/types/types.go +++ b/types/types.go @@ -24,7 +24,19 @@ type Output struct { type Account struct { Sequence uint 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 }