Merge pull request #88 from getamis/feature/generate-account-for-load-testing

container, k8s, tests: generate more accounts for load testing
This commit is contained in:
Miya Chen 2017-10-02 00:24:08 +08:00 committed by GitHub
commit 9cd60a5e53
10 changed files with 95 additions and 51 deletions

View File

@ -504,8 +504,13 @@ func (bc *blockchain) setupValidators(ips []net.IP, keys []*ecdsa.PrivateKey, of
opts = append(opts, HostWebSocketPort(freeport.GetPort())) opts = append(opts, HostWebSocketPort(freeport.GetPort()))
opts = append(opts, Key(keys[i])) opts = append(opts, Key(keys[i]))
opts = append(opts, HostIP(ips[i])) opts = append(opts, HostIP(ips[i]))
accounts := bc.accounts[i+offset : i+offset+1] accounts := bc.accounts[i+offset : i+offset+1]
opts = append(opts, Accounts(accounts)) var addrs []common.Address
for _, acc := range accounts {
addrs = append(addrs, acc.Address)
}
opts = append(opts, Accounts(addrs))
// Add PRIVATE_CONFIG for quorum // Add PRIVATE_CONFIG for quorum
if bc.isQuorum { if bc.isQuorum {

View File

@ -36,7 +36,6 @@ import (
"github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/network"
docker "github.com/docker/docker/client" docker "github.com/docker/docker/client"
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
@ -86,7 +85,7 @@ type Ethereum interface {
StartMining() error StartMining() error
StopMining() error StopMining() error
Accounts() []accounts.Account Accounts() []common.Address
DockerEnv() []string DockerEnv() []string
DockerBinds() []string DockerBinds() []string
@ -135,7 +134,7 @@ type ethereum struct {
hostName string hostName string
containerID string containerID string
node *discover.Node node *discover.Node
accounts []accounts.Account accounts []common.Address
password string password string
//Quorum only //Quorum only
@ -672,7 +671,7 @@ func (eth *ethereum) StopMining() error {
return client.StopMining(context.Background()) return client.StopMining(context.Background())
} }
func (eth *ethereum) Accounts() []accounts.Account { func (eth *ethereum) Accounts() []common.Address {
return eth.accounts return eth.accounts
} }

View File

@ -22,8 +22,8 @@ import (
"net" "net"
"path/filepath" "path/filepath"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
) )
type Option func(*ethereum) type Option func(*ethereum)
@ -293,7 +293,7 @@ func NoUSB() Option {
} }
} }
func Accounts(accounts []accounts.Account) Option { func Accounts(accounts []common.Address) Option {
return func(eth *ethereum) { return func(eth *ethereum) {
eth.accounts = accounts eth.accounts = accounts
} }

View File

@ -17,21 +17,36 @@
package k8s package k8s
import ( import (
"crypto/ecdsa"
"errors" "errors"
"fmt" "fmt"
"time" "time"
"github.com/ethereum/go-ethereum/common"
"github.com/getamis/istanbul-tools/charts" "github.com/getamis/istanbul-tools/charts"
istcommon "github.com/getamis/istanbul-tools/common" istcommon "github.com/getamis/istanbul-tools/common"
"github.com/getamis/istanbul-tools/container" "github.com/getamis/istanbul-tools/container"
) )
func NewBlockchain(numOfValidators int, gaslimit uint64, options ...Option) (bc *blockchain) { func NewBlockchain(numOfValidators int, numOfExtraAccounts int, gaslimit uint64, options ...Option) (bc *blockchain) {
_, nodekeys, addrs := istcommon.GenerateKeys(numOfValidators) _, nodekeys, addrs := istcommon.GenerateKeys(numOfValidators)
ips := istcommon.GenerateIPs(len(nodekeys)) ips := istcommon.GenerateIPs(len(nodekeys))
extraKeys := make([][]*ecdsa.PrivateKey, numOfValidators)
extraAddrs := make([][]common.Address, numOfValidators)
allAddrs := addrs
if numOfExtraAccounts > 0 {
for i := 0; i < numOfValidators; i++ {
extraKeys[i], _, extraAddrs[i] = istcommon.GenerateKeys(numOfExtraAccounts)
allAddrs = append(allAddrs, extraAddrs[i]...)
}
}
bc = &blockchain{ bc = &blockchain{
genesis: charts.NewGenesisChart(addrs, uint64(gaslimit)), genesis: charts.NewGenesisChart(allAddrs, uint64(gaslimit)),
staticNodes: charts.NewStaticNodesChart(nodekeys, ips), staticNodes: charts.NewStaticNodesChart(nodekeys, ips),
} }
@ -44,7 +59,7 @@ func NewBlockchain(numOfValidators int, gaslimit uint64, options ...Option) (bc
bc.genesis.Uninstall() bc.genesis.Uninstall()
return nil return nil
} }
bc.setupValidators(numOfValidators, nodekeys, ips, options...) bc.setupValidators(numOfValidators, extraKeys, nodekeys, ips, options...)
return bc return bc
} }
@ -104,7 +119,7 @@ func (bc *blockchain) Validators() []container.Ethereum {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
func (bc *blockchain) setupValidators(num int, nodekeys []string, ips []string, options ...Option) { func (bc *blockchain) setupValidators(num int, extraKeys [][]*ecdsa.PrivateKey, nodekeys []string, ips []string, options ...Option) {
for i := 0; i < num; i++ { for i := 0; i < num; i++ {
var opts []Option var opts []Option
opts = append(opts, options...) opts = append(opts, options...)
@ -112,6 +127,7 @@ func (bc *blockchain) setupValidators(num int, nodekeys []string, ips []string,
opts = append(opts, Name(fmt.Sprintf("%d", i))) opts = append(opts, Name(fmt.Sprintf("%d", i)))
opts = append(opts, NodeKeyHex(nodekeys[i])) opts = append(opts, NodeKeyHex(nodekeys[i]))
opts = append(opts, IPAddress(ips[i])) opts = append(opts, IPAddress(ips[i]))
opts = append(opts, ExtraAccounts(extraKeys[i]))
geth := NewEthereum( geth := NewEthereum(
opts..., opts...,

View File

@ -23,6 +23,7 @@ import (
func ExampleK8SBlockchain() { func ExampleK8SBlockchain() {
chain := NewBlockchain( chain := NewBlockchain(
4, 4,
0,
21000*1000, 21000*1000,
ImageRepository("quay.io/amis/geth"), ImageRepository("quay.io/amis/geth"),
ImageTag("istanbul_develop"), ImageTag("istanbul_develop"),

View File

@ -28,7 +28,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
@ -66,6 +65,7 @@ type ethereum struct {
nodekey string nodekey string
key *ecdsa.PrivateKey key *ecdsa.PrivateKey
accounts []*ecdsa.PrivateKey
k8sClient *kubernetes.Clientset k8sClient *kubernetes.Clientset
} }
@ -351,8 +351,11 @@ func (eth *ethereum) StopMining() error {
return nil return nil
} }
func (eth *ethereum) Accounts() []accounts.Account { func (eth *ethereum) Accounts() (addrs []common.Address) {
return nil for _, acc := range eth.accounts {
addrs = append(addrs, crypto.PubkeyToAddress(acc.PublicKey))
}
return addrs
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -16,7 +16,10 @@
package k8s package k8s
import "fmt" import (
"crypto/ecdsa"
"fmt"
)
type Option func(*ethereum) type Option func(*ethereum)
@ -86,3 +89,9 @@ func Verbosity(verbosity int) Option {
eth.args = append(eth.args, fmt.Sprintf("ethereum.verbosity=%d", verbosity)) eth.args = append(eth.args, fmt.Sprintf("ethereum.verbosity=%d", verbosity))
} }
} }
func ExtraAccounts(keys []*ecdsa.PrivateKey) Option {
return func(eth *ethereum) {
eth.accounts = keys
}
}

View File

@ -18,39 +18,51 @@ package k8s
import ( import (
"context" "context"
"errors"
"math/big" "math/big"
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto"
"github.com/getamis/istanbul-tools/client"
istcommon "github.com/getamis/istanbul-tools/common" istcommon "github.com/getamis/istanbul-tools/common"
) )
type Transactor interface { type Transactor interface {
SendTransactions(context.Context, common.Address, *big.Int, time.Duration) error SendTransactions(*client.Client, *big.Int, time.Duration) error
} }
func (eth *ethereum) SendTransactions(ctx context.Context, to common.Address, amount *big.Int, duration time.Duration) error { func (eth *ethereum) SendTransactions(client *client.Client, amount *big.Int, duration time.Duration) error {
client := eth.NewClient() var fns []func() error
if client == nil { for i, key := range eth.accounts {
return errors.New("failed to retrieve client") i := i
} key := key
nonce, err := client.NonceAt(context.Background(), eth.Address(), nil) fn := func() error {
if err != nil { fromAddr := crypto.PubkeyToAddress(key.PublicKey)
log.Error("Failed to get nonce", "addr", eth.Address(), "err", err) toAddr := crypto.PubkeyToAddress(eth.accounts[(i+1)%len(eth.accounts)].PublicKey)
return err timeout := time.After(duration)
}
timeout := time.After(duration) nonce, err := client.NonceAt(context.Background(), fromAddr, nil)
for { if err != nil {
select { log.Error("Failed to get nonce", "addr", fromAddr, "err", err)
case <-timeout: return err
return nil }
default:
_ = istcommon.SendEther(client, eth.key, to, amount, nonce) for {
nonce++ select {
case <-timeout:
return nil
default:
if err := istcommon.SendEther(client, key, toAddr, amount, nonce); err != nil {
return err
}
nonce++
}
}
} }
fns = append(fns, fn)
} }
return executeInParallel(fns...)
} }

View File

@ -17,7 +17,6 @@
package load package load
import ( import (
"context"
"math/big" "math/big"
"sync" "sync"
"testing" "testing"
@ -42,12 +41,10 @@ var _ = Describe("TPS-01: Large amount of transactions", func() {
runTests(numberOfValidators, gaslimit, txpoolSize) runTests(numberOfValidators, gaslimit, txpoolSize)
}, },
tests.Case("2048", 2048),
tests.Case("10240", 10240), tests.Case("10240", 10240),
) )
}, },
tests.Case("21000*1000", 21000*1000),
tests.Case("21000*3000", 21000*3000), tests.Case("21000*3000", 21000*3000),
) )
@ -63,12 +60,14 @@ func runTests(numberOfValidators int, gaslimit int, txpoolSize int) {
blockchain container.Blockchain blockchain container.Blockchain
sendEtherAddrs map[common.Address]common.Address sendEtherAddrs map[common.Address]common.Address
duration = 10 * time.Minute duration = 10 * time.Minute
accountsPerGeth = 30
) )
BeforeEach(func() { BeforeEach(func() {
blockchain = k8s.NewBlockchain( blockchain = k8s.NewBlockchain(
numberOfValidators, numberOfValidators,
accountsPerGeth,
uint64(gaslimit), uint64(gaslimit),
k8s.ImageRepository("quay.io/amis/geth"), k8s.ImageRepository("quay.io/amis/geth"),
k8s.ImageTag("istanbul_develop"), k8s.ImageTag("istanbul_develop"),
@ -104,13 +103,13 @@ func runTests(numberOfValidators int, gaslimit int, txpoolSize int) {
transactor, ok := geth.(k8s.Transactor) transactor, ok := geth.(k8s.Transactor)
Expect(ok).To(BeTrue()) Expect(ok).To(BeTrue())
Expect( client := geth.NewClient()
transactor.SendTransactions( Expect(client).NotTo(BeNil())
context.Background(),
sendEtherAddrs[geth.Address()], Expect(transactor.SendTransactions(
new(big.Int).Exp(big.NewInt(10), big.NewInt(3), nil), client,
duration), new(big.Int).Exp(big.NewInt(10), big.NewInt(3), nil),
).To(BeNil()) duration)).To(BeNil())
wg.Done() wg.Done()
}) })

View File

@ -72,7 +72,7 @@ var _ = Describe("QFS-08: Private transaction", func() {
acc := geth0.Accounts()[0] acc := geth0.Accounts()[0]
client0 := geth0.NewClient() client0 := geth0.NewClient()
byteCode := genByteCodeWithValue(storedValue) byteCode := genByteCodeWithValue(storedValue)
hash, err := client0.CreateContract(context.Background(), acc.Address, byteCode, big.NewInt(300000)) hash, err := client0.CreateContract(context.Background(), acc, byteCode, big.NewInt(300000))
Expect(err).To(BeNil()) Expect(err).To(BeNil())
txHash = common.HexToHash(hash) txHash = common.HexToHash(hash)
}) })
@ -105,7 +105,7 @@ var _ = Describe("QFS-08: Private transaction", func() {
ct1 := constellationNetwork.GetConstellation(1) ct1 := constellationNetwork.GetConstellation(1)
pubKey1 := ct1.PublicKeys() pubKey1 := ct1.PublicKeys()
byteCode := genByteCodeWithValue(storedValue) byteCode := genByteCodeWithValue(storedValue)
hash, err := client0.CreatePrivateContract(context.Background(), acc.Address, byteCode, big.NewInt(300000), pubKey1) hash, err := client0.CreatePrivateContract(context.Background(), acc, byteCode, big.NewInt(300000), pubKey1)
Expect(err).To(BeNil()) Expect(err).To(BeNil())
txHash = common.HexToHash(hash) txHash = common.HexToHash(hash)
}) })
@ -136,7 +136,7 @@ var _ = Describe("QFS-08: Private transaction", func() {
ct3 := constellationNetwork.GetConstellation(3) ct3 := constellationNetwork.GetConstellation(3)
pubKey3 := ct3.PublicKeys() pubKey3 := ct3.PublicKeys()
byteCode := genByteCodeWithValue(storedValue) byteCode := genByteCodeWithValue(storedValue)
hash, err := client2.CreatePrivateContract(context.Background(), acc.Address, byteCode, big.NewInt(300000), pubKey3) hash, err := client2.CreatePrivateContract(context.Background(), acc, byteCode, big.NewInt(300000), pubKey3)
Expect(err).To(BeNil()) Expect(err).To(BeNil())
txHash = common.HexToHash(hash) txHash = common.HexToHash(hash)
}) })
@ -165,7 +165,7 @@ var _ = Describe("QFS-08: Private transaction", func() {
acc := geth0.Accounts()[0] acc := geth0.Accounts()[0]
client0 := geth0.NewClient() client0 := geth0.NewClient()
byteCode := genByteCodeWithValue(storedValue) byteCode := genByteCodeWithValue(storedValue)
hash, err := client0.CreateContract(context.Background(), acc.Address, byteCode, big.NewInt(300000)) hash, err := client0.CreateContract(context.Background(), acc, byteCode, big.NewInt(300000))
Expect(err).To(BeNil()) Expect(err).To(BeNil())
txHash = common.HexToHash(hash) txHash = common.HexToHash(hash)
}) })