gecko/xputtest/chainwallet/wallet.go

145 lines
3.5 KiB
Go
Raw Normal View History

2020-03-10 12:20:34 -07:00
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package chainwallet
import (
"errors"
2020-03-10 12:20:34 -07:00
"fmt"
"github.com/ava-labs/gecko/ids"
"github.com/ava-labs/gecko/snow"
"github.com/ava-labs/gecko/utils/crypto"
2020-03-18 13:10:03 -07:00
"github.com/ava-labs/gecko/utils/logging"
2020-03-10 12:20:34 -07:00
"github.com/ava-labs/gecko/vms/spchainvm"
)
// Wallet is a holder for keys and UTXOs.
type Wallet struct {
2020-03-18 13:10:03 -07:00
networkID uint32
chainID ids.ID
log logging.Logger
keychain *spchainvm.Keychain // Mapping from public address to the SigningKeys
2020-03-10 12:20:34 -07:00
accountSet map[[20]byte]spchainvm.Account // Mapping from addresses to accounts
balance uint64
txs []*spchainvm.Tx
2020-03-10 12:20:34 -07:00
}
// NewWallet ...
2020-03-18 13:10:03 -07:00
func NewWallet(log logging.Logger, networkID uint32, chainID ids.ID) *Wallet {
2020-03-17 13:07:33 -07:00
return &Wallet{
2020-03-10 12:20:34 -07:00
networkID: networkID,
chainID: chainID,
2020-03-18 13:10:03 -07:00
log: log,
keychain: spchainvm.NewKeychain(networkID, chainID),
2020-03-10 12:20:34 -07:00
accountSet: make(map[[20]byte]spchainvm.Account),
}
}
// CreateAddress returns a brand new address! Ready to receive funds!
2020-03-17 13:07:33 -07:00
func (w *Wallet) CreateAddress() (ids.ShortID, error) {
sk, err := w.keychain.New()
if err != nil {
return ids.ShortID{}, err
}
return sk.PublicKey().Address(), nil
}
2020-03-10 12:20:34 -07:00
// ImportKey imports a private key into this wallet
func (w *Wallet) ImportKey(sk *crypto.PrivateKeySECP256K1R) { w.keychain.Add(sk) }
2020-03-10 12:20:34 -07:00
// AddAccount adds a new account to this wallet, if this wallet can spend it.
func (w *Wallet) AddAccount(account spchainvm.Account) {
if account.Balance() > 0 {
w.accountSet[account.ID().Key()] = account
w.balance += account.Balance()
}
}
// Balance returns the amount of the assets in this wallet
func (w *Wallet) Balance() uint64 { return w.balance }
// GenerateTxs generates the transactions that will be sent
// during the test
// Generate them all on test initialization so tx generation is not bottleneck
// in testing
func (w *Wallet) GenerateTxs(numTxs int) error {
2020-03-18 13:10:03 -07:00
w.log.Info("Generating %d transactions", numTxs)
2020-03-10 12:20:34 -07:00
ctx := snow.DefaultContextTest()
ctx.NetworkID = w.networkID
ctx.ChainID = w.chainID
2020-03-18 13:10:03 -07:00
frequency := numTxs / 50
if frequency > 1000 {
frequency = 1000
}
w.txs = make([]*spchainvm.Tx, numTxs)
2020-03-17 13:07:33 -07:00
for i := range w.txs {
tx, err := w.MakeTx()
if err != nil {
return err
2020-03-10 12:20:34 -07:00
}
2020-03-18 13:10:03 -07:00
if numGenerated := i + 1; numGenerated%frequency == 0 {
w.log.Info("Generated %d out of %d transactions", numGenerated, numTxs)
}
2020-03-17 13:07:33 -07:00
w.txs[i] = tx
2020-03-10 12:20:34 -07:00
}
2020-03-18 13:10:03 -07:00
w.log.Info("Finished generating %d transactions", numTxs)
return nil
2020-03-10 12:20:34 -07:00
}
2020-03-17 13:07:33 -07:00
// NextTx returns the next tx to be sent as part of xput test
func (w *Wallet) NextTx() *spchainvm.Tx {
if len(w.txs) == 0 {
return nil
}
tx := w.txs[0]
w.txs = w.txs[1:]
return tx
}
// MakeTx creates a new transaction and update the state to after the tx is accepted
func (w *Wallet) MakeTx() (*spchainvm.Tx, error) {
2020-03-10 12:20:34 -07:00
ctx := snow.DefaultContextTest()
ctx.NetworkID = w.networkID
ctx.ChainID = w.chainID
for _, account := range w.accountSet {
accountID := account.ID()
2020-03-17 13:07:33 -07:00
key, exists := w.keychain.Get(accountID)
if !exists {
return nil, errors.New("missing account")
2020-03-10 12:20:34 -07:00
}
2020-03-17 13:07:33 -07:00
amount := uint64(1)
tx, sendAccount, err := account.CreateTx(amount, accountID, ctx, key)
if err != nil {
continue
}
newAccount, err := sendAccount.Receive(tx, ctx)
if err != nil {
return nil, err
}
w.accountSet[accountID.Key()] = newAccount
return tx, nil
2020-03-10 12:20:34 -07:00
}
2020-03-17 13:07:33 -07:00
return nil, errors.New("empty")
2020-03-10 12:20:34 -07:00
}
func (w Wallet) String() string {
return fmt.Sprintf(
"Keychain:\n"+
2020-03-10 12:20:34 -07:00
"%s",
w.keychain.PrefixedString(" "))
2020-03-10 12:20:34 -07:00
}