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 (
|
2020-03-13 14:31:23 -07:00
|
|
|
"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"
|
|
|
|
"github.com/ava-labs/gecko/vms/spchainvm"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Wallet is a holder for keys and UTXOs.
|
|
|
|
type Wallet struct {
|
|
|
|
networkID uint32
|
|
|
|
chainID ids.ID
|
2020-03-13 14:31:23 -07:00
|
|
|
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
|
2020-03-13 14:31:23 -07:00
|
|
|
|
|
|
|
txs []*spchainvm.Tx
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewWallet ...
|
|
|
|
func NewWallet(networkID uint32, chainID ids.ID) Wallet {
|
|
|
|
return Wallet{
|
|
|
|
networkID: networkID,
|
|
|
|
chainID: chainID,
|
2020-03-13 14:31:23 -07:00
|
|
|
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-13 14:31:23 -07:00
|
|
|
func (w *Wallet) CreateAddress() ids.ShortID { return w.keychain.New().PublicKey().Address() }
|
2020-03-10 12:20:34 -07:00
|
|
|
|
|
|
|
// ImportKey imports a private key into this wallet
|
2020-03-13 14:31:23 -07:00
|
|
|
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
|
2020-03-13 14:31:23 -07:00
|
|
|
func (w *Wallet) GenerateTxs(numTxs int) error {
|
2020-03-10 12:20:34 -07:00
|
|
|
ctx := snow.DefaultContextTest()
|
|
|
|
ctx.NetworkID = w.networkID
|
|
|
|
ctx.ChainID = w.chainID
|
|
|
|
|
2020-03-13 14:31:23 -07:00
|
|
|
w.txs = make([]*spchainvm.Tx, numTxs)
|
|
|
|
for i := 0; i < numTxs; {
|
2020-03-10 12:20:34 -07:00
|
|
|
for _, account := range w.accountSet {
|
2020-03-13 14:31:23 -07:00
|
|
|
if i >= numTxs {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2020-03-10 12:20:34 -07:00
|
|
|
accountID := account.ID()
|
2020-03-13 14:31:23 -07:00
|
|
|
key, exists := w.keychain.Get(accountID)
|
|
|
|
if !exists {
|
|
|
|
return errors.New("missing account")
|
|
|
|
}
|
|
|
|
|
|
|
|
amount := uint64(1)
|
|
|
|
tx, sendAccount, err := account.CreateTx(amount, accountID, ctx, key)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
2020-03-13 14:31:23 -07:00
|
|
|
|
|
|
|
newAccount, err := sendAccount.Receive(tx, ctx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
w.accountSet[accountID.Key()] = newAccount
|
|
|
|
w.txs[i] = tx
|
|
|
|
i++
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
|
|
|
}
|
2020-03-13 14:31:23 -07:00
|
|
|
return nil
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
// Send a new transaction
|
|
|
|
func (w *Wallet) Send() *spchainvm.Tx {
|
|
|
|
ctx := snow.DefaultContextTest()
|
|
|
|
ctx.NetworkID = w.networkID
|
|
|
|
ctx.ChainID = w.chainID
|
|
|
|
|
|
|
|
for _, account := range w.accountSet {
|
|
|
|
accountID := account.ID()
|
2020-03-13 14:31:23 -07:00
|
|
|
if key, exists := w.keychain.Get(accountID); exists {
|
2020-03-10 12:20:34 -07:00
|
|
|
amount := uint64(1)
|
|
|
|
if tx, sendAccount, err := account.CreateTx(amount, accountID, ctx, key); err == nil {
|
|
|
|
newAccount, err := sendAccount.Receive(tx, ctx)
|
|
|
|
if err == nil {
|
|
|
|
w.accountSet[accountID.Key()] = newAccount
|
|
|
|
return tx
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
// NextTx returns the next tx to be sent as part of xput test
|
|
|
|
func (w *Wallet) NextTx() *spchainvm.Tx {
|
2020-03-13 14:31:23 -07:00
|
|
|
if len(w.txs) == 0 {
|
2020-03-10 12:20:34 -07:00
|
|
|
return nil
|
|
|
|
}
|
2020-03-13 14:31:23 -07:00
|
|
|
tx := w.txs[0]
|
|
|
|
w.txs = w.txs[1:]
|
|
|
|
return tx
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (w Wallet) String() string {
|
|
|
|
return fmt.Sprintf(
|
2020-03-13 14:31:23 -07:00
|
|
|
"Keychain:\n"+
|
2020-03-10 12:20:34 -07:00
|
|
|
"%s",
|
2020-03-13 14:31:23 -07:00
|
|
|
w.keychain.PrefixedString(" "))
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|