Merge branch 'sim_txs' into develop
This commit is contained in:
commit
d83ee27b6a
|
@ -54,8 +54,10 @@ func (acc *Account) Copy() *Account {
|
|||
}
|
||||
|
||||
func (acc *Account) String() string {
|
||||
// return fmt.Sprintf("Account{%X:%v C:%v S:%X}", acc.Address, acc.PubKey, len(acc.Code), acc.StorageRoot)
|
||||
return fmt.Sprintf("Account{%X:%v C:%v S:%X P:%s}", acc.Address, acc.PubKey, len(acc.Code), acc.StorageRoot, acc.Permissions)
|
||||
if acc == nil {
|
||||
return "nil-Account"
|
||||
}
|
||||
return fmt.Sprintf("Account{%X:%v B:%v C:%v S:%X P:%s}", acc.Address, acc.PubKey, acc.Balance, len(acc.Code), acc.StorageRoot, acc.Permissions)
|
||||
}
|
||||
|
||||
func AccountEncoder(o interface{}, w io.Writer, n *int64, err *error) {
|
||||
|
|
|
@ -12,6 +12,27 @@ type PrivAccount struct {
|
|||
PrivKey PrivKey `json:"priv_key"`
|
||||
}
|
||||
|
||||
func (pA *PrivAccount) Generate(index int) *PrivAccount {
|
||||
newPrivKey := pA.PrivKey.(PrivKeyEd25519).Generate(index)
|
||||
newPubKey := newPrivKey.PubKey()
|
||||
newAddress := newPubKey.Address()
|
||||
return &PrivAccount{
|
||||
Address: newAddress,
|
||||
PubKey: newPubKey,
|
||||
PrivKey: newPrivKey,
|
||||
}
|
||||
}
|
||||
|
||||
func (pA *PrivAccount) Sign(chainID string, o Signable) Signature {
|
||||
return pA.PrivKey.Sign(SignBytes(chainID, o))
|
||||
}
|
||||
|
||||
func (pA *PrivAccount) String() string {
|
||||
return Fmt("PrivAccount{%X}", pA.Address)
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
// Generates a new account with private key.
|
||||
func GenPrivAccount() *PrivAccount {
|
||||
privKeyBytes := new([64]byte)
|
||||
|
@ -41,21 +62,18 @@ func GenPrivAccountFromSecret(secret []byte) *PrivAccount {
|
|||
}
|
||||
}
|
||||
|
||||
func GenPrivAccountFromKey(privKeyBytes [64]byte) *PrivAccount {
|
||||
pubKeyBytes := ed25519.MakePublicKey(&privKeyBytes)
|
||||
func GenPrivAccountFromPrivKeyBytes(privKeyBytes []byte) *PrivAccount {
|
||||
if len(privKeyBytes) != 64 {
|
||||
panic(Fmt("Expected 64 bytes but got %v", len(privKeyBytes)))
|
||||
}
|
||||
privKeyBytes64 := [64]byte{}
|
||||
copy(privKeyBytes64[:], privKeyBytes)
|
||||
pubKeyBytes := ed25519.MakePublicKey(&privKeyBytes64)
|
||||
pubKey := PubKeyEd25519(pubKeyBytes[:])
|
||||
privKey := PrivKeyEd25519(privKeyBytes[:])
|
||||
privKey := PrivKeyEd25519(privKeyBytes)
|
||||
return &PrivAccount{
|
||||
Address: pubKey.Address(),
|
||||
PubKey: pubKey,
|
||||
PrivKey: privKey,
|
||||
}
|
||||
}
|
||||
|
||||
func (privAccount *PrivAccount) Sign(chainID string, o Signable) Signature {
|
||||
return privAccount.PrivKey.Sign(SignBytes(chainID, o))
|
||||
}
|
||||
|
||||
func (privAccount *PrivAccount) String() string {
|
||||
return Fmt("PrivAccount{%X}", privAccount.Address)
|
||||
}
|
||||
|
|
|
@ -29,12 +29,12 @@ var _ = binary.RegisterInterface(
|
|||
// Implements PrivKey
|
||||
type PrivKeyEd25519 []byte
|
||||
|
||||
func (privKey PrivKeyEd25519) Sign(msg []byte) Signature {
|
||||
pubKey := privKey.PubKey().(PubKeyEd25519)
|
||||
privKeyBytes := new([64]byte)
|
||||
copy(privKeyBytes[:32], privKey[:])
|
||||
copy(privKeyBytes[32:], pubKey[:])
|
||||
signatureBytes := ed25519.Sign(privKeyBytes, msg)
|
||||
func (key PrivKeyEd25519) Sign(msg []byte) Signature {
|
||||
pubKey := key.PubKey().(PubKeyEd25519)
|
||||
keyBytes := new([64]byte)
|
||||
copy(keyBytes[:32], key[:])
|
||||
copy(keyBytes[32:], pubKey[:])
|
||||
signatureBytes := ed25519.Sign(keyBytes, msg)
|
||||
return SignatureEd25519(signatureBytes[:])
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,15 @@ func (privKey PrivKeyEd25519) String() string {
|
|||
return Fmt("PrivKeyEd25519{*****}")
|
||||
}
|
||||
|
||||
// Deterministically generates new priv-key bytes from key.
|
||||
func (key PrivKeyEd25519) Generate(index int) PrivKeyEd25519 {
|
||||
newBytes := binary.BinarySha256(struct {
|
||||
PrivKey []byte
|
||||
Index int
|
||||
}{key, index})
|
||||
return PrivKeyEd25519(newBytes)
|
||||
}
|
||||
|
||||
func GenPrivKeyEd25519() PrivKeyEd25519 {
|
||||
privKeyBytes := new([64]byte)
|
||||
copy(privKeyBytes[:32], CRandBytes(32))
|
||||
|
|
|
@ -31,4 +31,4 @@ func (sig SignatureEd25519) IsNil() bool { return false }
|
|||
|
||||
func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 }
|
||||
|
||||
func (sig SignatureEd25519) String() string { return fmt.Sprintf("%X", Fingerprint(sig)) }
|
||||
func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig)) }
|
||||
|
|
|
@ -17,11 +17,15 @@ func ReadBinary(o interface{}, r io.Reader, n *int64, err *error) interface{} {
|
|||
rv, rt := reflect.ValueOf(o), reflect.TypeOf(o)
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
if rv.IsNil() {
|
||||
rv = reflect.New(rt.Elem())
|
||||
o = rv.Interface()
|
||||
// This allows ReadBinaryObject() to return a nil pointer,
|
||||
// if the value read is nil.
|
||||
rvPtr := reflect.New(rt)
|
||||
ReadBinaryPtr(rvPtr.Interface(), r, n, err)
|
||||
return rvPtr.Elem().Interface()
|
||||
} else {
|
||||
readReflectBinary(rv, rt, Options{}, r, n, err)
|
||||
return o
|
||||
}
|
||||
readReflectBinary(rv, rt, Options{}, r, n, err)
|
||||
return o
|
||||
} else {
|
||||
ptrRv := reflect.New(rt)
|
||||
readReflectBinary(ptrRv.Elem(), rt, Options{}, r, n, err)
|
||||
|
@ -69,11 +73,15 @@ func ReadJSONObject(o interface{}, object interface{}, err *error) interface{} {
|
|||
rv, rt := reflect.ValueOf(o), reflect.TypeOf(o)
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
if rv.IsNil() {
|
||||
rv = reflect.New(rt.Elem())
|
||||
o = rv.Interface()
|
||||
// This allows ReadJSONObject() to return a nil pointer
|
||||
// if the value read is nil.
|
||||
rvPtr := reflect.New(rt)
|
||||
ReadJSONObjectPtr(rvPtr.Interface(), object, err)
|
||||
return rvPtr.Elem().Interface()
|
||||
} else {
|
||||
readReflectJSON(rv, rt, object, err)
|
||||
return o
|
||||
}
|
||||
readReflectJSON(rv, rt, object, err)
|
||||
return o
|
||||
} else {
|
||||
ptrRv := reflect.New(rt)
|
||||
readReflectJSON(ptrRv.Elem(), rt, object, err)
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
)
|
||||
|
||||
const Version = "0.0.1"
|
||||
const sleepSeconds = 1 // Every minute
|
||||
const sleepSeconds = 1 // Every second
|
||||
|
||||
// Parse command-line options
|
||||
func parseFlags() (chopSize int64, limitSize int64, version bool, logFiles []string) {
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
Simulate the Economy of Texas.
|
||||
|
||||
```bash
|
||||
sim_txs --priv-key "PRIV_KEY_HEX" --num-accounts 1000 --remote localhost:46657
|
||||
```
|
||||
|
||||
The above uses the rpc-host to fetch the account state for the account with given priv-key,
|
||||
then deterministically generates num-accounts more accounts to spread the coins around.
|
||||
|
||||
It's a test utility.
|
|
@ -0,0 +1,173 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"flag"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
acm "github.com/tendermint/tendermint/account"
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
"github.com/tendermint/tendermint/rpc/client"
|
||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
const Version = "0.0.1"
|
||||
const sleepSeconds = 1 // Every second
|
||||
|
||||
// Parse command-line options
|
||||
func parseFlags() (privKeyHex string, numAccounts int, remote string, version bool) {
|
||||
flag.StringVar(&privKeyHex, "priv-key", "", "Private key bytes in HEX")
|
||||
flag.IntVar(&numAccounts, "num-accounts", 1000, "Deterministically generates this many sub-accounts")
|
||||
flag.StringVar(&remote, "remote", "http://localhost:46657", "Remote RPC host:port")
|
||||
flag.BoolVar(&version, "version", false, "Version")
|
||||
flag.Parse()
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
// Read options
|
||||
privKeyHex, numAccounts, remote, version := parseFlags()
|
||||
if version {
|
||||
fmt.Println(Fmt("sim_txs version %v", Version))
|
||||
return
|
||||
}
|
||||
|
||||
// Print args.
|
||||
// fmt.Println(privKeyHex, numAccounts, remote, version)
|
||||
|
||||
privKeyBytes, err := hex.DecodeString(privKeyHex)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
root := acm.GenPrivAccountFromPrivKeyBytes(privKeyBytes)
|
||||
fmt.Println("Computed address: %X", root.Address)
|
||||
|
||||
// Get root account.
|
||||
rootAccount, err := getAccount(remote, root.Address)
|
||||
if err != nil {
|
||||
fmt.Println(Fmt("Root account does not exist: %X", root.Address))
|
||||
return
|
||||
} else {
|
||||
fmt.Println("Root account", rootAccount)
|
||||
}
|
||||
|
||||
go func() {
|
||||
// Construct a new send Tx
|
||||
accounts := make([]*acm.Account, numAccounts)
|
||||
privAccounts := make([]*acm.PrivAccount, numAccounts)
|
||||
for i := 0; i < numAccounts; i++ {
|
||||
privAccounts[i] = root.Generate(i)
|
||||
account, err := getAccount(remote, privAccounts[i].Address)
|
||||
if err != nil {
|
||||
fmt.Println("Error", err)
|
||||
return
|
||||
} else {
|
||||
accounts[i] = account
|
||||
}
|
||||
}
|
||||
for {
|
||||
sendTx := makeRandomTransaction(rootAccount, root, accounts, privAccounts)
|
||||
// Broadcast it.
|
||||
err := broadcastSendTx(remote, sendTx)
|
||||
if err != nil {
|
||||
Exit(Fmt("Failed to broadcast SendTx: %v", err))
|
||||
return
|
||||
}
|
||||
// Broadcast 1 tx!
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
}()
|
||||
|
||||
// Trap signal
|
||||
TrapSignal(func() {
|
||||
fmt.Println("sim_txs shutting down")
|
||||
})
|
||||
}
|
||||
|
||||
func getAccount(remote string, address []byte) (*acm.Account, error) {
|
||||
// var account *acm.Account = new(acm.Account)
|
||||
account, err := rpcclient.Call(remote, "get_account", []interface{}{address}, (*acm.Account)(nil))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if account.(*acm.Account) == nil {
|
||||
return &acm.Account{Address: address}, nil
|
||||
} else {
|
||||
return account.(*acm.Account), nil
|
||||
}
|
||||
}
|
||||
|
||||
func broadcastSendTx(remote string, sendTx *types.SendTx) error {
|
||||
receipt, err := rpcclient.Call(remote, "broadcast_tx", []interface{}{sendTx}, (*ctypes.Receipt)(nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("Broadcast receipt:", receipt)
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeRandomTransaction(rootAccount *acm.Account, rootPrivAccount *acm.PrivAccount, accounts []*acm.Account, privAccounts []*acm.PrivAccount) *types.SendTx {
|
||||
allAccounts := append(accounts, rootAccount)
|
||||
allPrivAccounts := append(privAccounts, rootPrivAccount)
|
||||
|
||||
// Find accout with the most money
|
||||
inputBalance := int64(0)
|
||||
inputAccount := (*acm.Account)(nil)
|
||||
inputPrivAccount := (*acm.PrivAccount)(nil)
|
||||
for i, account := range allAccounts {
|
||||
if account == nil {
|
||||
continue
|
||||
}
|
||||
if inputBalance < account.Balance {
|
||||
inputBalance = account.Balance
|
||||
inputAccount = account
|
||||
inputPrivAccount = allPrivAccounts[i]
|
||||
}
|
||||
}
|
||||
if inputAccount == nil {
|
||||
Exit("No accounts have any money")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Find a selection of accounts to send to
|
||||
outputAccounts := map[string]*acm.Account{}
|
||||
for i := 0; i < 2; i++ {
|
||||
for {
|
||||
idx := RandInt() % len(accounts)
|
||||
if bytes.Equal(accounts[idx].Address, inputAccount.Address) {
|
||||
continue
|
||||
}
|
||||
if _, ok := outputAccounts[string(accounts[idx].Address)]; ok {
|
||||
continue
|
||||
}
|
||||
outputAccounts[string(accounts[idx].Address)] = accounts[idx]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Construct SendTx
|
||||
sendTx := types.NewSendTx()
|
||||
err := sendTx.AddInputWithNonce(inputPrivAccount.PubKey, inputAccount.Balance, inputAccount.Sequence+1)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, outputAccount := range outputAccounts {
|
||||
sendTx.AddOutput(outputAccount.Address, inputAccount.Balance/int64(len(outputAccounts)))
|
||||
// XXX FIXME???
|
||||
outputAccount.Balance += inputAccount.Balance / int64(len(outputAccounts))
|
||||
}
|
||||
|
||||
// Sign SendTx
|
||||
sendTx.SignInput("tendermint_testnet_7", 0, inputPrivAccount)
|
||||
|
||||
// Hack: Listen for events or create a new RPC call for this.
|
||||
// XXX FIXME
|
||||
inputAccount.Sequence += 1
|
||||
inputAccount.Balance = 0 // FIXME???
|
||||
|
||||
return sendTx
|
||||
}
|
|
@ -3,7 +3,7 @@ package crawler
|
|||
import (
|
||||
"fmt"
|
||||
"github.com/tendermint/tendermint/binary"
|
||||
rpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
rpcclient "github.com/tendermint/tendermint/rpc/core_client"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
"time"
|
||||
|
@ -35,7 +35,7 @@ type Node struct {
|
|||
ChainID string
|
||||
BlockHeight int
|
||||
BlockHistory map[int]time.Time // when we saw each block
|
||||
NetInfo *rpctypes.ResponseNetInfo
|
||||
NetInfo *ctypes.ResponseNetInfo
|
||||
|
||||
Validator bool
|
||||
|
||||
|
@ -48,7 +48,7 @@ func (n *Node) Address() string {
|
|||
}
|
||||
|
||||
// Set the basic status and chain_id info for a node from RPC responses
|
||||
func (n *Node) SetInfo(status *rpctypes.ResponseStatus, netinfo *rpctypes.ResponseNetInfo) {
|
||||
func (n *Node) SetInfo(status *ctypes.ResponseStatus, netinfo *ctypes.ResponseNetInfo) {
|
||||
n.LastSeen = time.Now()
|
||||
n.ChainID = status.NodeInfo.ChainID
|
||||
n.BlockHeight = status.LatestBlockHeight
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"fmt"
|
||||
acm "github.com/tendermint/tendermint/account"
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
ptypes "github.com/tendermint/tendermint/permission/types"
|
||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
)
|
||||
|
||||
|
@ -12,20 +11,12 @@ func GenPrivAccount() (*acm.PrivAccount, error) {
|
|||
return acm.GenPrivAccount(), nil
|
||||
}
|
||||
|
||||
// If the account is not known, returns nil, nil.
|
||||
func GetAccount(address []byte) (*acm.Account, error) {
|
||||
cache := mempoolReactor.Mempool.GetCache()
|
||||
account := cache.GetAccount(address)
|
||||
if account == nil {
|
||||
// XXX: shouldn't we return "account not found"?
|
||||
account = &acm.Account{
|
||||
Address: address,
|
||||
PubKey: nil,
|
||||
Sequence: 0,
|
||||
Balance: 0,
|
||||
Code: nil,
|
||||
StorageRoot: nil,
|
||||
Permissions: cache.GetAccount(ptypes.GlobalPermissionsAddress).Permissions,
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
return account, nil
|
||||
}
|
||||
|
@ -34,7 +25,7 @@ func GetStorage(address, key []byte) (*ctypes.ResponseGetStorage, error) {
|
|||
state := consensusState.GetState()
|
||||
account := state.GetAccount(address)
|
||||
if account == nil {
|
||||
return nil, fmt.Errorf("Unknown address: %X", address)
|
||||
return nil, fmt.Errorf("UnknownAddress: %X", address)
|
||||
}
|
||||
storageRoot := account.StorageRoot
|
||||
storageTree := state.LoadStorage(storageRoot)
|
||||
|
@ -62,7 +53,7 @@ func DumpStorage(address []byte) (*ctypes.ResponseDumpStorage, error) {
|
|||
state := consensusState.GetState()
|
||||
account := state.GetAccount(address)
|
||||
if account == nil {
|
||||
return nil, fmt.Errorf("Unknown address: %X", address)
|
||||
return nil, fmt.Errorf("UnknownAddress: %X", address)
|
||||
}
|
||||
storageRoot := account.StorageRoot
|
||||
storageTree := state.LoadStorage(storageRoot)
|
||||
|
|
|
@ -33,10 +33,10 @@ func BlockchainInfo(minHeight, maxHeight int) (*ctypes.ResponseBlockchainInfo, e
|
|||
|
||||
func GetBlock(height int) (*ctypes.ResponseGetBlock, error) {
|
||||
if height == 0 {
|
||||
return nil, fmt.Errorf("height must be greater than 0")
|
||||
return nil, fmt.Errorf("Height must be greater than 0")
|
||||
}
|
||||
if height > blockStore.Height() {
|
||||
return nil, fmt.Errorf("height must be less than the current blockchain height")
|
||||
return nil, fmt.Errorf("Height must be less than the current blockchain height")
|
||||
}
|
||||
|
||||
blockMeta := blockStore.LoadBlockMeta(height)
|
||||
|
|
|
@ -3,7 +3,7 @@ set -euo pipefail
|
|||
IFS=$'\n\t'
|
||||
|
||||
debora run -- bash -c "cd \$GOPATH/src/github.com/tendermint/tendermint; killall tendermint; killall logjack"
|
||||
debora run -- bash -c "cd \$GOPATH/src/github.com/tendermint/tendermint; tendermint unsafe_reset_priv_validator; rm -rf ~/.tendermint/data"
|
||||
debora run -- bash -c "cd \$GOPATH/src/github.com/tendermint/tendermint; tendermint unsafe_reset_priv_validator; rm -rf ~/.tendermint/data; rm ~/.tendermint/genesis.json"
|
||||
debora run -- bash -c "cd \$GOPATH/src/github.com/tendermint/tendermint; git pull origin develop; make"
|
||||
debora run -- bash -c "cd \$GOPATH/src/github.com/tendermint/tendermint; mkdir -p ~/.tendermint/logs"
|
||||
debora run --bg --label tendermint -- bash -c "cd \$GOPATH/src/github.com/tendermint/tendermint; tendermint node | stdinwriter -outpath ~/.tendermint/logs/tendermint.log"
|
||||
|
|
|
@ -70,7 +70,7 @@ func TestCallTxSignable(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBondTxSignable(t *testing.T) {
|
||||
privAccount := account.GenPrivAccountFromKey([64]byte{})
|
||||
privAccount := account.GenPrivAccountFromPrivKeyBytes(make([]byte, 64))
|
||||
bondTx := &BondTx{
|
||||
PubKey: privAccount.PubKey.(account.PubKeyEd25519),
|
||||
Inputs: []*TxInput{
|
||||
|
|
Loading…
Reference in New Issue