Merge pull request #64 from getamis/test/account-tx-sending-tools
container: add account for each geth
This commit is contained in:
commit
a21d4c162c
|
@ -116,6 +116,48 @@ func (ic *Client) StopMining(ctx context.Context) error {
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func (ic *Client) SendTransaction(ctx context.Context, from, to common.Address, value *big.Int) (txHash string, err error) {
|
||||||
|
var hex hexutil.Bytes
|
||||||
|
arg := map[string]interface{}{
|
||||||
|
"from": from,
|
||||||
|
"to": to,
|
||||||
|
"value": (*hexutil.Big)(value),
|
||||||
|
}
|
||||||
|
if err = ic.c.CallContext(ctx, &hex, "eth_sendTransaction", arg); err == nil {
|
||||||
|
txHash = hex.String()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ic *Client) CreateContract(ctx context.Context, from common.Address, bytecode string, gas *big.Int) (txHash string, err error) {
|
||||||
|
var hex hexutil.Bytes
|
||||||
|
arg := map[string]interface{}{
|
||||||
|
"from": from,
|
||||||
|
"gas": (*hexutil.Big)(gas),
|
||||||
|
"data": bytecode,
|
||||||
|
}
|
||||||
|
if err = ic.c.CallContext(ctx, &hex, "eth_sendTransaction", arg); err == nil {
|
||||||
|
txHash = hex.String()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ic *Client) CreatePrivateContract(ctx context.Context, from common.Address, bytecode string, gas *big.Int, privateFor []string) (txHash string, err error) {
|
||||||
|
var hex hexutil.Bytes
|
||||||
|
arg := map[string]interface{}{
|
||||||
|
"from": from,
|
||||||
|
"gas": (*hexutil.Big)(gas),
|
||||||
|
"data": bytecode,
|
||||||
|
"privateFor": privateFor,
|
||||||
|
}
|
||||||
|
if err = ic.c.CallContext(ctx, &hex, "eth_sendTransaction", arg); err == nil {
|
||||||
|
txHash = hex.String()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
func (ic *Client) ProposeValidator(ctx context.Context, address common.Address, auth bool) error {
|
func (ic *Client) ProposeValidator(ctx context.Context, address common.Address, auth bool) error {
|
||||||
var r []byte
|
var r []byte
|
||||||
// TODO: Result needs to be verified with other method
|
// TODO: Result needs to be verified with other method
|
||||||
|
|
|
@ -191,10 +191,10 @@ func (c *Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (*big.In
|
||||||
return c.ethClient.EstimateGas(ctx, msg)
|
return c.ethClient.EstimateGas(ctx, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendTransaction injects a signed transaction into the pending pool for execution.
|
// SendRawTransaction injects a signed transaction into the pending pool for execution.
|
||||||
//
|
//
|
||||||
// If the transaction was a contract creation use the TransactionReceipt method to get the
|
// If the transaction was a contract creation use the TransactionReceipt method to get the
|
||||||
// contract address after the transaction has been mined.
|
// contract address after the transaction has been mined.
|
||||||
func (c *Client) SendTransaction(ctx context.Context, tx *types.Transaction) error {
|
func (c *Client) SendRawTransaction(ctx context.Context, tx *types.Transaction) error {
|
||||||
return c.ethClient.SendTransaction(ctx, tx)
|
return c.ethClient.SendTransaction(ctx, tx)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/getamis/go-ethereum/p2p/discover"
|
"github.com/getamis/go-ethereum/p2p/discover"
|
||||||
|
@ -50,7 +51,7 @@ func GenerateIPs(num int) (ips []string) {
|
||||||
func GenerateRandomDir() (string, error) {
|
func GenerateRandomDir() (string, error) {
|
||||||
err := os.MkdirAll(filepath.Join(defaultLocalDir), 0700)
|
err := os.MkdirAll(filepath.Join(defaultLocalDir), 0700)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceDir := filepath.Join(defaultLocalDir, fmt.Sprintf("%s-%s", clientIdentifier, uuid.NewV4().String()))
|
instanceDir := filepath.Join(defaultLocalDir, fmt.Sprintf("%s-%s", clientIdentifier, uuid.NewV4().String()))
|
||||||
|
@ -62,6 +63,27 @@ func GenerateRandomDir() (string, error) {
|
||||||
return instanceDir, nil
|
return instanceDir, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GeneratePasswordFile(dir string, filename string, password string) {
|
||||||
|
path := filepath.Join(dir, filename)
|
||||||
|
err := ioutil.WriteFile(path, []byte(password), 0644)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to generate password file, err:%v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CopyKeystore(dir string, accounts []accounts.Account) {
|
||||||
|
keystorePath := filepath.Join(dir, "keystore")
|
||||||
|
err := os.MkdirAll(keystorePath, 0744)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to copy keystore, err:%v", err)
|
||||||
|
}
|
||||||
|
for _, a := range accounts {
|
||||||
|
src := a.URL.Path
|
||||||
|
dst := filepath.Join(keystorePath, filepath.Base(src))
|
||||||
|
copyFile(src, dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func GenerateKeys(num int) (keys []*ecdsa.PrivateKey, nodekeys []string, addrs []common.Address) {
|
func GenerateKeys(num int) (keys []*ecdsa.PrivateKey, nodekeys []string, addrs []common.Address) {
|
||||||
for i := 0; i < num; i++ {
|
for i := 0; i < num; i++ {
|
||||||
nodekey := RandomHex()[2:]
|
nodekey := RandomHex()[2:]
|
||||||
|
@ -147,3 +169,14 @@ func RandomBytes(len int) ([]byte, error) {
|
||||||
|
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyFile(src string, dst string) {
|
||||||
|
data, err := ioutil.ReadFile(src)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(dst, data, 0644)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -20,13 +20,17 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
|
"math/big"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/phayes/freeport"
|
"github.com/phayes/freeport"
|
||||||
|
|
||||||
|
@ -34,6 +38,13 @@ import (
|
||||||
"github.com/getamis/istanbul-tools/genesis"
|
"github.com/getamis/istanbul-tools/genesis"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
allocBalance = "900000000000000000000000000000000000000000000"
|
||||||
|
veryLightScryptN = 2
|
||||||
|
veryLightScryptP = 1
|
||||||
|
defaultPassword = ""
|
||||||
|
)
|
||||||
|
|
||||||
type Blockchain interface {
|
type Blockchain interface {
|
||||||
AddValidators(numOfValidators int) ([]Ethereum, error)
|
AddValidators(numOfValidators int) ([]Ethereum, error)
|
||||||
RemoveValidators(candidates []Ethereum, t time.Duration) error
|
RemoveValidators(candidates []Ethereum, t time.Duration) error
|
||||||
|
@ -66,6 +77,9 @@ func NewBlockchain(network *DockerNetwork, numOfValidators int, options ...Optio
|
||||||
bc.getFreeIPAddrs = network.GetFreeIPAddrs
|
bc.getFreeIPAddrs = network.GetFreeIPAddrs
|
||||||
bc.opts = append(bc.opts, DockerNetworkName(bc.dockerNetworkName))
|
bc.opts = append(bc.opts, DockerNetworkName(bc.dockerNetworkName))
|
||||||
|
|
||||||
|
//Create accounts
|
||||||
|
bc.generateAccounts(numOfValidators)
|
||||||
|
|
||||||
bc.addValidators(numOfValidators)
|
bc.addValidators(numOfValidators)
|
||||||
return bc
|
return bc
|
||||||
}
|
}
|
||||||
|
@ -85,6 +99,8 @@ func NewDefaultBlockchain(network *DockerNetwork, numOfValidators int) (bc *bloc
|
||||||
Etherbase("1a9afb711302c5f83b5902843d1c007a1a137632"),
|
Etherbase("1a9afb711302c5f83b5902843d1c007a1a137632"),
|
||||||
Mine(),
|
Mine(),
|
||||||
SyncMode("full"),
|
SyncMode("full"),
|
||||||
|
Unlock(0),
|
||||||
|
Password("password.txt"),
|
||||||
Logging(false),
|
Logging(false),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -101,6 +117,8 @@ func NewDefaultBlockchainWithFaulty(network *DockerNetwork, numOfNormal int, num
|
||||||
Etherbase("1a9afb711302c5f83b5902843d1c007a1a137632"),
|
Etherbase("1a9afb711302c5f83b5902843d1c007a1a137632"),
|
||||||
Mine(),
|
Mine(),
|
||||||
SyncMode("full"),
|
SyncMode("full"),
|
||||||
|
Unlock(0),
|
||||||
|
Password("password.txt"),
|
||||||
Logging(false)}
|
Logging(false)}
|
||||||
normalOpts := make([]Option, len(commonOpts), len(commonOpts)+2)
|
normalOpts := make([]Option, len(commonOpts), len(commonOpts)+2)
|
||||||
copy(normalOpts, commonOpts[:])
|
copy(normalOpts, commonOpts[:])
|
||||||
|
@ -138,14 +156,17 @@ func NewDefaultBlockchainWithFaulty(network *DockerNetwork, numOfNormal int, num
|
||||||
log.Fatalf("Failed to get free ip addresses, err: %v", err)
|
log.Fatalf("Failed to get free ip addresses, err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Create accounts
|
||||||
|
bc.generateAccounts(totalNodes)
|
||||||
|
|
||||||
keys, _, addrs := istcommon.GenerateKeys(totalNodes)
|
keys, _, addrs := istcommon.GenerateKeys(totalNodes)
|
||||||
bc.setupGenesis(addrs)
|
bc.setupGenesis(addrs)
|
||||||
// Create normal validators
|
// Create normal validators
|
||||||
bc.opts = normalOpts
|
bc.opts = normalOpts
|
||||||
bc.setupValidators(ips[:numOfNormal], keys[:numOfNormal], bc.opts...)
|
bc.setupValidators(ips[:numOfNormal], keys[:numOfNormal], 0, bc.opts...)
|
||||||
// Create faulty validators
|
// Create faulty validators
|
||||||
bc.opts = faultyOpts
|
bc.opts = faultyOpts
|
||||||
bc.setupValidators(ips[numOfNormal:], keys[numOfNormal:], bc.opts...)
|
bc.setupValidators(ips[numOfNormal:], keys[numOfNormal:], numOfNormal, bc.opts...)
|
||||||
return bc
|
return bc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,6 +193,9 @@ func NewQuorumBlockchain(network *DockerNetwork, ctn ConstellationNetwork, optio
|
||||||
bc.getFreeIPAddrs = network.GetFreeIPAddrs
|
bc.getFreeIPAddrs = network.GetFreeIPAddrs
|
||||||
bc.opts = append(bc.opts, DockerNetworkName(bc.dockerNetworkName))
|
bc.opts = append(bc.opts, DockerNetworkName(bc.dockerNetworkName))
|
||||||
|
|
||||||
|
//Create accounts
|
||||||
|
bc.generateAccounts(ctn.NumOfConstellations())
|
||||||
|
|
||||||
bc.addValidators(ctn.NumOfConstellations())
|
bc.addValidators(ctn.NumOfConstellations())
|
||||||
return bc
|
return bc
|
||||||
}
|
}
|
||||||
|
@ -190,6 +214,9 @@ func NewDefaultQuorumBlockchain(network *DockerNetwork, ctn ConstellationNetwork
|
||||||
NoDiscover(),
|
NoDiscover(),
|
||||||
Etherbase("1a9afb711302c5f83b5902843d1c007a1a137632"),
|
Etherbase("1a9afb711302c5f83b5902843d1c007a1a137632"),
|
||||||
Mine(),
|
Mine(),
|
||||||
|
SyncMode("full"),
|
||||||
|
Unlock(0),
|
||||||
|
Password("password.txt"),
|
||||||
Logging(false),
|
Logging(false),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -206,6 +233,8 @@ type blockchain struct {
|
||||||
validators []Ethereum
|
validators []Ethereum
|
||||||
opts []Option
|
opts []Option
|
||||||
constellationNetwork ConstellationNetwork
|
constellationNetwork ConstellationNetwork
|
||||||
|
accounts []accounts.Account
|
||||||
|
keystorePath string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *blockchain) AddValidators(numOfValidators int) ([]Ethereum, error) {
|
func (bc *blockchain) AddValidators(numOfValidators int) ([]Ethereum, error) {
|
||||||
|
@ -356,7 +385,7 @@ func (bc *blockchain) addValidators(numOfValidators int) error {
|
||||||
}
|
}
|
||||||
keys, _, addrs := istcommon.GenerateKeys(numOfValidators)
|
keys, _, addrs := istcommon.GenerateKeys(numOfValidators)
|
||||||
bc.setupGenesis(addrs)
|
bc.setupGenesis(addrs)
|
||||||
bc.setupValidators(ips, keys, bc.opts...)
|
bc.setupValidators(ips, keys, 0, bc.opts...)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -381,15 +410,37 @@ func (bc *blockchain) connectAll(strong bool) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bc *blockchain) generateAccounts(num int) {
|
||||||
|
// Create keystore object
|
||||||
|
d, err := ioutil.TempDir("", "istanbul-keystore")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to create temp folder for keystore", err)
|
||||||
|
}
|
||||||
|
ks := keystore.NewKeyStore(d, veryLightScryptN, veryLightScryptP)
|
||||||
|
bc.keystorePath = d
|
||||||
|
|
||||||
|
// Create accounts
|
||||||
|
for i := 0; i < num; i++ {
|
||||||
|
a, e := ks.NewAccount(defaultPassword)
|
||||||
|
if e != nil {
|
||||||
|
log.Fatalf("Failed to create account", err)
|
||||||
|
}
|
||||||
|
bc.accounts = append(bc.accounts, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (bc *blockchain) setupGenesis(addrs []common.Address) {
|
func (bc *blockchain) setupGenesis(addrs []common.Address) {
|
||||||
|
balance, _ := new(big.Int).SetString(allocBalance, 10)
|
||||||
if bc.genesisFile == "" {
|
if bc.genesisFile == "" {
|
||||||
bc.genesisFile = genesis.NewFile(bc.isQuorum,
|
bc.genesisFile = genesis.NewFile(bc.isQuorum,
|
||||||
genesis.Validators(addrs...),
|
genesis.Validators(addrs...),
|
||||||
|
genesis.Alloc(bc.accounts, balance),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *blockchain) setupValidators(ips []net.IP, keys []*ecdsa.PrivateKey, options ...Option) {
|
// Offset: offset is for account index offset
|
||||||
|
func (bc *blockchain) setupValidators(ips []net.IP, keys []*ecdsa.PrivateKey, offset int, options ...Option) {
|
||||||
for i := 0; i < len(keys); i++ {
|
for i := 0; i < len(keys); i++ {
|
||||||
var opts []Option
|
var opts []Option
|
||||||
opts = append(opts, options...)
|
opts = append(opts, options...)
|
||||||
|
@ -403,6 +454,9 @@ func (bc *blockchain) setupValidators(ips []net.IP, keys []*ecdsa.PrivateKey, op
|
||||||
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]
|
||||||
|
opts = append(opts, Accounts(accounts))
|
||||||
|
|
||||||
// Add PRIVATE_CONFIG for quorum
|
// Add PRIVATE_CONFIG for quorum
|
||||||
if bc.isQuorum {
|
if bc.isQuorum {
|
||||||
ct := bc.constellationNetwork.GetConstellation(i)
|
ct := bc.constellationNetwork.GetConstellation(i)
|
||||||
|
@ -416,6 +470,10 @@ func (bc *blockchain) setupValidators(ips []net.IP, keys []*ecdsa.PrivateKey, op
|
||||||
opts...,
|
opts...,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Copy keystore to datadir
|
||||||
|
istcommon.GeneratePasswordFile(dataDir, geth.password, defaultPassword)
|
||||||
|
istcommon.CopyKeystore(dataDir, accounts)
|
||||||
|
|
||||||
err = geth.Init(bc.genesisFile)
|
err = geth.Init(bc.genesisFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Failed to init genesis", err)
|
log.Fatal("Failed to init genesis", err)
|
||||||
|
|
|
@ -33,6 +33,7 @@ func TestEthereumBlockchain(t *testing.T) {
|
||||||
WebSocketAPI("admin,eth,net,web3,personal"),
|
WebSocketAPI("admin,eth,net,web3,personal"),
|
||||||
WebSocketOrigin("*"),
|
WebSocketOrigin("*"),
|
||||||
NoDiscover(),
|
NoDiscover(),
|
||||||
|
Password("password.txt"),
|
||||||
Logging(true),
|
Logging(true),
|
||||||
)
|
)
|
||||||
defer chain.Finalize()
|
defer chain.Finalize()
|
||||||
|
|
|
@ -130,6 +130,8 @@ type Constellation interface {
|
||||||
ConfigPath() string
|
ConfigPath() string
|
||||||
// Binds() returns volume binding paths
|
// Binds() returns volume binding paths
|
||||||
Binds() []string
|
Binds() []string
|
||||||
|
// PublicKeys() return public keys
|
||||||
|
PublicKeys() []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConstellation(c *client.Client, options ...ConstellationOption) *constellation {
|
func NewConstellation(c *client.Client, options ...ConstellationOption) *constellation {
|
||||||
|
@ -363,6 +365,15 @@ func (ct *constellation) Binds() []string {
|
||||||
return []string{ct.localWorkDir + ":" + ct.workDir}
|
return []string{ct.localWorkDir + ":" + ct.workDir}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ct *constellation) PublicKeys() []string {
|
||||||
|
keyPath := ct.localKeyPath("pub")
|
||||||
|
keyBytes, err := ioutil.ReadFile(keyPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Unable to read key file")
|
||||||
|
}
|
||||||
|
return []string{string(keyBytes)}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constellation internal functions
|
* Constellation internal functions
|
||||||
**/
|
**/
|
||||||
|
@ -386,6 +397,10 @@ func (ct *constellation) keyPath(extension string) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ct *constellation) localKeyPath(extension string) string {
|
||||||
|
return filepath.Join(ct.localWorkDir, fmt.Sprintf("%s.%s", ct.keyName, extension))
|
||||||
|
}
|
||||||
|
|
||||||
func (ct *constellation) localConfigPath() string {
|
func (ct *constellation) localConfigPath() string {
|
||||||
return filepath.Join(ct.localWorkDir, fmt.Sprintf("%s.conf", ct.keyName))
|
return filepath.Join(ct.localWorkDir, fmt.Sprintf("%s.conf", ct.keyName))
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ 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"
|
||||||
|
@ -82,6 +83,8 @@ type Ethereum interface {
|
||||||
StartMining() error
|
StartMining() error
|
||||||
StopMining() error
|
StopMining() error
|
||||||
|
|
||||||
|
Accounts() []accounts.Account
|
||||||
|
|
||||||
DockerEnv() []string
|
DockerEnv() []string
|
||||||
DockerBinds() []string
|
DockerBinds() []string
|
||||||
}
|
}
|
||||||
|
@ -129,6 +132,8 @@ type ethereum struct {
|
||||||
hostName string
|
hostName string
|
||||||
containerID string
|
containerID string
|
||||||
node *discover.Node
|
node *discover.Node
|
||||||
|
accounts []accounts.Account
|
||||||
|
password string
|
||||||
|
|
||||||
//Quorum only
|
//Quorum only
|
||||||
isQuorum bool
|
isQuorum bool
|
||||||
|
@ -603,6 +608,10 @@ func (eth *ethereum) StopMining() error {
|
||||||
return client.StopMining(context.Background())
|
return client.StopMining(context.Background())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (eth *ethereum) Accounts() []accounts.Account {
|
||||||
|
return eth.accounts
|
||||||
|
}
|
||||||
|
|
||||||
func (eth *ethereum) DockerEnv() []string {
|
func (eth *ethereum) DockerEnv() []string {
|
||||||
return eth.dockerEnv
|
return eth.dockerEnv
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,9 @@ import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -290,3 +292,24 @@ func NoUSB() Option {
|
||||||
eth.flags = append(eth.flags, "--"+utils.NoUSBFlag.Name)
|
eth.flags = append(eth.flags, "--"+utils.NoUSBFlag.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Accounts(accounts []accounts.Account) Option {
|
||||||
|
return func(eth *ethereum) {
|
||||||
|
eth.accounts = accounts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Unlock(index int) Option {
|
||||||
|
return func(eth *ethereum) {
|
||||||
|
eth.flags = append(eth.flags, "--"+utils.UnlockedAccountFlag.Name)
|
||||||
|
eth.flags = append(eth.flags, fmt.Sprintf("%d", index))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Password(password string) Option {
|
||||||
|
return func(eth *ethereum) {
|
||||||
|
eth.password = password
|
||||||
|
eth.flags = append(eth.flags, "--"+utils.PasswordFileFlag.Name)
|
||||||
|
eth.flags = append(eth.flags, filepath.Join(utils.DataDirFlag.Value.Value, password))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,7 +18,9 @@ package genesis
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
@ -43,3 +45,13 @@ func GasLimit(limit uint64) Option {
|
||||||
genesis.GasLimit = limit
|
genesis.GasLimit = limit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Alloc(accounts []accounts.Account, balance *big.Int) Option {
|
||||||
|
return func(genesis *core.Genesis) {
|
||||||
|
alloc := make(map[common.Address]core.GenesisAccount)
|
||||||
|
for _, a := range accounts {
|
||||||
|
alloc[a.Address] = core.GenesisAccount{Balance: balance}
|
||||||
|
}
|
||||||
|
genesis.Alloc = alloc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,233 @@
|
||||||
|
// Code generated - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package contract
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SimplestorageABI is the input ABI used to generate the binding from.
|
||||||
|
const SimplestorageABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"storedData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"retVal\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"initVal\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"constructor\"}]"
|
||||||
|
|
||||||
|
// SimplestorageBin is the compiled bytecode used for deploying new contracts.
|
||||||
|
const SimplestorageBin = `0x6060604052341561000c57fe5b6040516020806100fa83398101604052515b60008190555b505b60c6806100346000396000f300606060405263ffffffff60e060020a6000350416632a1afcd98114603457806360fe47b11460535780636d4ce63c146065575bfe5b3415603b57fe5b60416084565b60408051918252519081900360200190f35b3415605a57fe5b6063600435608a565b005b3415606c57fe5b60416093565b60408051918252519081900360200190f35b60005481565b60008190555b50565b6000545b905600a165627a7a72305820fc8a42e6cfcb798ea356ac3f059ddefd56b41db474058cfbd48f75225d280f9a0029`
|
||||||
|
|
||||||
|
// DeploySimplestorage deploys a new Ethereum contract, binding an instance of Simplestorage to it.
|
||||||
|
func DeploySimplestorage(auth *bind.TransactOpts, backend bind.ContractBackend, initVal *big.Int) (common.Address, *types.Transaction, *Simplestorage, error) {
|
||||||
|
parsed, err := abi.JSON(strings.NewReader(SimplestorageABI))
|
||||||
|
if err != nil {
|
||||||
|
return common.Address{}, nil, nil, err
|
||||||
|
}
|
||||||
|
address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(SimplestorageBin), backend, initVal)
|
||||||
|
if err != nil {
|
||||||
|
return common.Address{}, nil, nil, err
|
||||||
|
}
|
||||||
|
return address, tx, &Simplestorage{SimplestorageCaller: SimplestorageCaller{contract: contract}, SimplestorageTransactor: SimplestorageTransactor{contract: contract}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simplestorage is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type Simplestorage struct {
|
||||||
|
SimplestorageCaller // Read-only binding to the contract
|
||||||
|
SimplestorageTransactor // Write-only binding to the contract
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimplestorageCaller is an auto generated read-only Go binding around an Ethereum contract.
|
||||||
|
type SimplestorageCaller struct {
|
||||||
|
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimplestorageTransactor is an auto generated write-only Go binding around an Ethereum contract.
|
||||||
|
type SimplestorageTransactor struct {
|
||||||
|
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimplestorageSession is an auto generated Go binding around an Ethereum contract,
|
||||||
|
// with pre-set call and transact options.
|
||||||
|
type SimplestorageSession struct {
|
||||||
|
Contract *Simplestorage // Generic contract binding to set the session for
|
||||||
|
CallOpts bind.CallOpts // Call options to use throughout this session
|
||||||
|
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimplestorageCallerSession is an auto generated read-only Go binding around an Ethereum contract,
|
||||||
|
// with pre-set call options.
|
||||||
|
type SimplestorageCallerSession struct {
|
||||||
|
Contract *SimplestorageCaller // Generic contract caller binding to set the session for
|
||||||
|
CallOpts bind.CallOpts // Call options to use throughout this session
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimplestorageTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
|
||||||
|
// with pre-set transact options.
|
||||||
|
type SimplestorageTransactorSession struct {
|
||||||
|
Contract *SimplestorageTransactor // Generic contract transactor binding to set the session for
|
||||||
|
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimplestorageRaw is an auto generated low-level Go binding around an Ethereum contract.
|
||||||
|
type SimplestorageRaw struct {
|
||||||
|
Contract *Simplestorage // Generic contract binding to access the raw methods on
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimplestorageCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
|
||||||
|
type SimplestorageCallerRaw struct {
|
||||||
|
Contract *SimplestorageCaller // Generic read-only contract binding to access the raw methods on
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimplestorageTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
|
||||||
|
type SimplestorageTransactorRaw struct {
|
||||||
|
Contract *SimplestorageTransactor // Generic write-only contract binding to access the raw methods on
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSimplestorage creates a new instance of Simplestorage, bound to a specific deployed contract.
|
||||||
|
func NewSimplestorage(address common.Address, backend bind.ContractBackend) (*Simplestorage, error) {
|
||||||
|
contract, err := bindSimplestorage(address, backend, backend)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Simplestorage{SimplestorageCaller: SimplestorageCaller{contract: contract}, SimplestorageTransactor: SimplestorageTransactor{contract: contract}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSimplestorageCaller creates a new read-only instance of Simplestorage, bound to a specific deployed contract.
|
||||||
|
func NewSimplestorageCaller(address common.Address, caller bind.ContractCaller) (*SimplestorageCaller, error) {
|
||||||
|
contract, err := bindSimplestorage(address, caller, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &SimplestorageCaller{contract: contract}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSimplestorageTransactor creates a new write-only instance of Simplestorage, bound to a specific deployed contract.
|
||||||
|
func NewSimplestorageTransactor(address common.Address, transactor bind.ContractTransactor) (*SimplestorageTransactor, error) {
|
||||||
|
contract, err := bindSimplestorage(address, nil, transactor)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &SimplestorageTransactor{contract: contract}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// bindSimplestorage binds a generic wrapper to an already deployed contract.
|
||||||
|
func bindSimplestorage(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor) (*bind.BoundContract, error) {
|
||||||
|
parsed, err := abi.JSON(strings.NewReader(SimplestorageABI))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bind.NewBoundContract(address, parsed, caller, transactor), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call invokes the (constant) contract method with params as input values and
|
||||||
|
// sets the output to result. The result type might be a single field for simple
|
||||||
|
// returns, a slice of interfaces for anonymous returns and a struct for named
|
||||||
|
// returns.
|
||||||
|
func (_Simplestorage *SimplestorageRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
|
||||||
|
return _Simplestorage.Contract.SimplestorageCaller.contract.Call(opts, result, method, params...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer initiates a plain transaction to move funds to the contract, calling
|
||||||
|
// its default method if one is available.
|
||||||
|
func (_Simplestorage *SimplestorageRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
|
||||||
|
return _Simplestorage.Contract.SimplestorageTransactor.contract.Transfer(opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transact invokes the (paid) contract method with params as input values.
|
||||||
|
func (_Simplestorage *SimplestorageRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
|
||||||
|
return _Simplestorage.Contract.SimplestorageTransactor.contract.Transact(opts, method, params...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call invokes the (constant) contract method with params as input values and
|
||||||
|
// sets the output to result. The result type might be a single field for simple
|
||||||
|
// returns, a slice of interfaces for anonymous returns and a struct for named
|
||||||
|
// returns.
|
||||||
|
func (_Simplestorage *SimplestorageCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
|
||||||
|
return _Simplestorage.Contract.contract.Call(opts, result, method, params...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer initiates a plain transaction to move funds to the contract, calling
|
||||||
|
// its default method if one is available.
|
||||||
|
func (_Simplestorage *SimplestorageTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
|
||||||
|
return _Simplestorage.Contract.contract.Transfer(opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transact invokes the (paid) contract method with params as input values.
|
||||||
|
func (_Simplestorage *SimplestorageTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
|
||||||
|
return _Simplestorage.Contract.contract.Transact(opts, method, params...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get is a free data retrieval call binding the contract method 0x6d4ce63c.
|
||||||
|
//
|
||||||
|
// Solidity: function get() constant returns(retVal uint256)
|
||||||
|
func (_Simplestorage *SimplestorageCaller) Get(opts *bind.CallOpts) (*big.Int, error) {
|
||||||
|
var (
|
||||||
|
ret0 = new(*big.Int)
|
||||||
|
)
|
||||||
|
out := ret0
|
||||||
|
err := _Simplestorage.contract.Call(opts, out, "get")
|
||||||
|
return *ret0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get is a free data retrieval call binding the contract method 0x6d4ce63c.
|
||||||
|
//
|
||||||
|
// Solidity: function get() constant returns(retVal uint256)
|
||||||
|
func (_Simplestorage *SimplestorageSession) Get() (*big.Int, error) {
|
||||||
|
return _Simplestorage.Contract.Get(&_Simplestorage.CallOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get is a free data retrieval call binding the contract method 0x6d4ce63c.
|
||||||
|
//
|
||||||
|
// Solidity: function get() constant returns(retVal uint256)
|
||||||
|
func (_Simplestorage *SimplestorageCallerSession) Get() (*big.Int, error) {
|
||||||
|
return _Simplestorage.Contract.Get(&_Simplestorage.CallOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StoredData is a free data retrieval call binding the contract method 0x2a1afcd9.
|
||||||
|
//
|
||||||
|
// Solidity: function storedData() constant returns(uint256)
|
||||||
|
func (_Simplestorage *SimplestorageCaller) StoredData(opts *bind.CallOpts) (*big.Int, error) {
|
||||||
|
var (
|
||||||
|
ret0 = new(*big.Int)
|
||||||
|
)
|
||||||
|
out := ret0
|
||||||
|
err := _Simplestorage.contract.Call(opts, out, "storedData")
|
||||||
|
return *ret0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StoredData is a free data retrieval call binding the contract method 0x2a1afcd9.
|
||||||
|
//
|
||||||
|
// Solidity: function storedData() constant returns(uint256)
|
||||||
|
func (_Simplestorage *SimplestorageSession) StoredData() (*big.Int, error) {
|
||||||
|
return _Simplestorage.Contract.StoredData(&_Simplestorage.CallOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StoredData is a free data retrieval call binding the contract method 0x2a1afcd9.
|
||||||
|
//
|
||||||
|
// Solidity: function storedData() constant returns(uint256)
|
||||||
|
func (_Simplestorage *SimplestorageCallerSession) StoredData() (*big.Int, error) {
|
||||||
|
return _Simplestorage.Contract.StoredData(&_Simplestorage.CallOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set is a paid mutator transaction binding the contract method 0x60fe47b1.
|
||||||
|
//
|
||||||
|
// Solidity: function set(x uint256) returns()
|
||||||
|
func (_Simplestorage *SimplestorageTransactor) Set(opts *bind.TransactOpts, x *big.Int) (*types.Transaction, error) {
|
||||||
|
return _Simplestorage.contract.Transact(opts, "set", x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set is a paid mutator transaction binding the contract method 0x60fe47b1.
|
||||||
|
//
|
||||||
|
// Solidity: function set(x uint256) returns()
|
||||||
|
func (_Simplestorage *SimplestorageSession) Set(x *big.Int) (*types.Transaction, error) {
|
||||||
|
return _Simplestorage.Contract.Set(&_Simplestorage.TransactOpts, x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set is a paid mutator transaction binding the contract method 0x60fe47b1.
|
||||||
|
//
|
||||||
|
// Solidity: function set(x uint256) returns()
|
||||||
|
func (_Simplestorage *SimplestorageTransactorSession) Set(x *big.Int) (*types.Transaction, error) {
|
||||||
|
return _Simplestorage.Contract.Set(&_Simplestorage.TransactOpts, x)
|
||||||
|
}
|
Loading…
Reference in New Issue