}
// NewManager creates a new account manager
-func NewManager(db, walletDB dbm.DB, walletHeightFn func() uint64, chain *protocol.Chain) *Manager {
+func NewManager(db, walletDB dbm.DB, chain *protocol.Chain) *Manager {
return &Manager{
db: db,
chain: chain,
- utxoDB: newReserver(chain, walletDB, walletHeightFn),
+ utxoDB: newReserver(chain, walletDB),
cache: lru.New(maxAccountCache),
aliasCache: lru.New(maxAccountCache),
delayedACPs: make(map[*txbuilder.TemplateBuilder][]*controlProgram),
AssetID: *a.AssetId,
AccountID: a.AccountID,
}
- res, err := a.accounts.utxoDB.Reserve(ctx, src, a.Amount, a.ClientToken, b.MaxTime())
+ res, err := a.accounts.utxoDB.Reserve(src, a.Amount, a.ClientToken, b.MaxTime())
if err != nil {
return errors.Wrap(err, "reserving utxos")
}
b.OnRollback(canceler(ctx, a.accounts, res.ID))
for _, r := range res.UTXOs {
- txInput, sigInst, err := utxoToInputs(ctx, acct, r, a.ReferenceData)
+ txInput, sigInst, err := utxoToInputs(acct, r, a.ReferenceData)
if err != nil {
return errors.Wrap(err, "creating inputs")
}
}
}
- txInput, sigInst, err := utxoToInputs(ctx, acct, res.UTXOs[0], a.ReferenceData)
+ txInput, sigInst, err := utxoToInputs(acct, res.UTXOs[0], a.ReferenceData)
if err != nil {
return err
}
}
}
-func utxoToInputs(ctx context.Context, account *signers.Signer, u *utxo, refData []byte) (
+func utxoToInputs(account *signers.Signer, u *utxo, refData []byte) (
*legacy.TxInput,
*txbuilder.SigningInstruction,
error,
log "github.com/sirupsen/logrus"
dbm "github.com/tendermint/tmlibs/db"
- "github.com/bytom/errors"
"github.com/bytom/config"
+ "github.com/bytom/errors"
"github.com/bytom/protocol"
"github.com/bytom/protocol/bc"
"github.com/bytom/sync/idempotency"
ClientToken *string
}
-func newReserver(c *protocol.Chain, walletdb dbm.DB, walletHeightFn func() uint64) *reserver {
+func newReserver(c *protocol.Chain, walletdb dbm.DB) *reserver {
return &reserver{
c: c,
db: walletdb,
- heightFn: walletHeightFn,
reservations: make(map[uint64]*reservation),
sources: make(map[source]*sourceReserver),
}
type reserver struct {
c *protocol.Chain
db dbm.DB
- heightFn func() uint64
nextReservationID uint64
idempotency idempotency.Group
// Reserve selects and reserves UTXOs according to the criteria provided
// in source. The resulting reservation expires at exp.
-func (re *reserver) Reserve(ctx context.Context, src source, amount uint64, clientToken *string, exp time.Time) (*reservation, error) {
+func (re *reserver) Reserve(src source, amount uint64, clientToken *string, exp time.Time) (*reservation, error) {
if clientToken == nil {
- return re.reserve(ctx, src, amount, clientToken, exp)
+ return re.reserve(src, amount, clientToken, exp)
}
untypedRes, err := re.idempotency.Once(*clientToken, func() (interface{}, error) {
- return re.reserve(ctx, src, amount, clientToken, exp)
+ return re.reserve(src, amount, clientToken, exp)
})
return untypedRes.(*reservation), err
}
-func (re *reserver) reserve(ctx context.Context, src source, amount uint64, clientToken *string, exp time.Time) (res *reservation, err error) {
+func (re *reserver) reserve(src source, amount uint64, clientToken *string, exp time.Time) (res *reservation, err error) {
sourceReserver := re.source(src)
// Try to reserve the right amount.
rid := atomic.AddUint64(&re.nextReservationID, 1)
- reserved, total, err := sourceReserver.reserve(ctx, rid, amount)
+ reserved, total, err := sourceReserver.reserve(rid, amount)
if err != nil {
return nil, err
}
}
func (re *reserver) reserveUTXO(ctx context.Context, out bc.Hash, exp time.Time, clientToken *string) (*reservation, error) {
- u, err := findSpecificUTXO(ctx, re.db, out)
+ u, err := findSpecificUTXO(re.db, out)
if err != nil {
return nil, err
}
db: re.db,
src: src,
validFn: re.checkUTXO,
- heightFn: re.heightFn,
cached: make(map[bc.Hash]*utxo),
reserved: make(map[bc.Hash]uint64),
}
db dbm.DB
src source
validFn func(u *utxo) bool
- heightFn func() uint64
-
- mu sync.Mutex
- cached map[bc.Hash]*utxo
- reserved map[bc.Hash]uint64
- lastHeight uint64
+ mu sync.Mutex
+ cached map[bc.Hash]*utxo
+ reserved map[bc.Hash]uint64
}
-func (sr *sourceReserver) reserve(ctx context.Context, rid uint64, amount uint64) ([]*utxo, uint64, error) {
+func (sr *sourceReserver) reserve(rid uint64, amount uint64) ([]*utxo, uint64, error) {
reservedUTXOs, reservedAmount, err := sr.reserveFromCache(rid, amount)
if err == nil {
return reservedUTXOs, reservedAmount, nil
}
// Find the set of UTXOs that match this source.
- err = sr.refillCache(ctx)
+ err = sr.refillCache()
if err != nil {
return nil, 0, err
}
}
}
-func (sr *sourceReserver) refillCache(ctx context.Context) error {
- sr.mu.Lock()
- lastHeight := sr.lastHeight
- sr.mu.Unlock()
-
- curHeight := sr.heightFn()
- if lastHeight >= curHeight {
- return nil
- }
+func (sr *sourceReserver) refillCache() error {
- utxos, err := findMatchingUTXOs(ctx, sr.db, sr.src)
+ utxos, err := findMatchingUTXOs(sr.db, sr.src)
if err != nil {
return errors.Wrap(err)
}
sr.mu.Lock()
- if curHeight > sr.lastHeight {
- sr.lastHeight = curHeight
- }
for _, u := range utxos {
sr.cached[u.OutputID] = u
}
return nil
}
-func findMatchingUTXOs(ctx context.Context, db dbm.DB, src source) ([]*utxo, error) {
+func findMatchingUTXOs(db dbm.DB, src source) ([]*utxo, error) {
var (
utxos []*utxo
return utxos, nil
}
-func findSpecificUTXO(ctx context.Context, db dbm.DB, outHash bc.Hash) (*utxo, error) {
+func findSpecificUTXO(db dbm.DB, outHash bc.Hash) (*utxo, error) {
u := new(utxo)
accountUTXO := new(UTXO)
Tags map[string]interface{}
RawDefinitionByte []byte
DefinitionMap map[string]interface{}
- BlockHeight uint64
}
func (asset *Asset) Definition() (map[string]interface{}, error) {
import (
"encoding/json"
- log "github.com/sirupsen/logrus"
-
"github.com/bytom/blockchain/query"
"github.com/bytom/blockchain/signers"
chainjson "github.com/bytom/encoding/json"
- "github.com/bytom/protocol/bc"
- "github.com/bytom/protocol/bc/legacy"
"github.com/bytom/protocol/vm/vmutil"
)
}
return aa, nil
}
-
-// IndexAssets is run on every block and indexes all non-local assets.
-func (reg *Registry) IndexAssets(b *legacy.Block) {
-
- var err error
- asset := Asset{}
- rawSaveAsset := make([]byte, 0)
- seen := make(map[bc.AssetID]bool)
- storeBatch := reg.db.NewBatch()
-
- for _, tx := range b.Transactions {
- for _, in := range tx.Inputs {
- if !in.IsIssuance() {
- continue
- }
- assetID := in.AssetID()
- if seen[assetID] {
- continue
- }
- inputIssue, ok := in.TypedInput.(*legacy.IssuanceInput)
- if !ok {
- continue
- }
-
- seen[assetID] = true
-
- if rawAsset := reg.db.Get([]byte(assetID.String())); rawAsset == nil {
- asset.RawDefinitionByte = inputIssue.AssetDefinition
- asset.AssetID = assetID
- asset.VMVersion = inputIssue.VMVersion
- asset.IssuanceProgram = in.IssuanceProgram()
- asset.BlockHeight = b.Height
- asset.InitialBlockHash = reg.initialBlockHash
- } else {
- if err = json.Unmarshal(rawAsset, &asset); err != nil {
- log.WithField("AssetID", assetID.String()).Warn("failed unmarshal saved asset")
- continue
- }
- //update block height which created at
- if asset.BlockHeight != 0 {
- continue
- }
- asset.BlockHeight = b.Height
- }
-
- rawSaveAsset, err = json.Marshal(&asset)
- if err != nil {
- log.WithField("AssetID", assetID.String()).Warn("failed marshal to save asset")
- continue
- }
-
- storeBatch.Set([]byte(assetID.String()), rawSaveAsset)
-
- }
- }
-
- storeBatch.Write()
-}
"github.com/bytom/blockchain/pseudohsm"
"github.com/bytom/blockchain/txbuilder"
"github.com/bytom/blockchain/txdb"
- w "github.com/bytom/blockchain/wallet"
cfg "github.com/bytom/config"
"github.com/bytom/crypto/ed25519/chainkd"
"github.com/bytom/protocol"
assetsDB := dbm.NewDB("asset", config.DBBackend, dir)
walletDB := dbm.NewDB("wallet", config.DBBackend, config.DBDir())
- accounts = account.NewManager(accountsDB, walletDB, w.GetWalletHeight, chain)
+ accounts = account.NewManager(accountsDB, walletDB, chain)
assets = asset.NewRegistry(assetsDB, chain)
hsm, err := pseudohsm.New(dirPath)
"github.com/bytom/protocol/bc/legacy"
)
-var walletkey = []byte("walletInfo")
+var walletKey = []byte("walletInfo")
//StatusInfo is base valid block info to handle orphan block rollback
type StatusInfo struct {
StatusInfo
}
-//GlobalWallet for sourceReserve heightFn
-var GlobalWallet Wallet
-
-//InitWallet return a new wallet instance
-func InitWallet(walletDB db.DB, accounts *account.Manager, assets *asset.Registry) *Wallet {
- GlobalWallet.DB = walletDB
- GlobalWallet.accounts = accounts
- GlobalWallet.assets = assets
- GlobalWallet.Ind = query.NewIndexer(walletDB)
-
- w := &GlobalWallet
+//NewWallet return a new wallet instance
+func NewWallet(walletDB db.DB, accounts *account.Manager, assets *asset.Registry) *Wallet {
+ w := &Wallet{
+ DB: walletDB,
+ accounts: accounts,
+ assets: assets,
+ Ind: query.NewIndexer(walletDB),
+ }
walletInfo, err := w.GetWalletInfo()
if err != nil {
log.WithField("warn", err).Warn("get wallet info")
return w
}
-//GetWalletHeight return wallet on current height
-func GetWalletHeight() uint64 {
- return GlobalWallet.Height
-}
-
//GetWalletInfo return stored wallet info and nil,if error,
//return initial wallet info and err
func (w *Wallet) GetWalletInfo() (StatusInfo, error) {
var info StatusInfo
var rawWallet []byte
- if rawWallet = w.DB.Get(walletkey); rawWallet == nil {
+ if rawWallet = w.DB.Get(walletKey); rawWallet == nil {
return info, nil
}
w.Height = block.Height
w.Hash = block.Hash()
- w.assets.IndexAssets(block)
w.accounts.BuildAccountUTXOs(&storeBatch, block)
//update wallet info and commit batch write
return
}
//update wallet to db
- (*batch).Set(walletkey, rawWallet)
+ (*batch).Set(walletKey, rawWallet)
//commit to db
(*batch).Write()
}
assetsDB := dbm.NewDB("asset", config.DBBackend, config.DBDir())
walletDB := dbm.NewDB("wallet", config.DBBackend, config.DBDir())
- accounts = account.NewManager(accountsDB, walletDB, w.GetWalletHeight, chain)
+ accounts = account.NewManager(accountsDB, walletDB, chain)
assets = asset.NewRegistry(assetsDB, chain)
- wallet = w.InitWallet(walletDB, accounts, assets)
+ wallet = w.NewWallet(walletDB, accounts, assets)
wallet.Ind.RegisterAnnotator(accounts.AnnotateTxs)
wallet.Ind.RegisterAnnotator(assets.AnnotateTxs)