core: store NEP5 balances separately
There is no need to take and unmarshal an account structure only to get it's NEP5 balances.
This commit is contained in:
parent
d25dddc780
commit
df2598c8dc
8 changed files with 81 additions and 37 deletions
|
@ -763,18 +763,15 @@ func (bc *Blockchain) processNEP5Transfer(cache *cachedDao, tx *transaction.Tran
|
||||||
Tx: tx.Hash(),
|
Tx: tx.Hash(),
|
||||||
}
|
}
|
||||||
if !fromAddr.Equals(util.Uint160{}) {
|
if !fromAddr.Equals(util.Uint160{}) {
|
||||||
acc, err := cache.GetAccountStateOrNew(fromAddr)
|
balances, err := cache.GetNEP5Balances(fromAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
bs := acc.NEP5Balances[sc]
|
bs := balances.Trackers[sc]
|
||||||
if bs == nil {
|
|
||||||
bs = new(state.NEP5Tracker)
|
|
||||||
acc.NEP5Balances[sc] = bs
|
|
||||||
}
|
|
||||||
bs.Balance -= amount
|
bs.Balance -= amount
|
||||||
bs.LastUpdatedBlock = b.Index
|
bs.LastUpdatedBlock = b.Index
|
||||||
if err := cache.PutAccountState(acc); err != nil {
|
balances.Trackers[sc] = bs
|
||||||
|
if err := cache.PutNEP5Balances(fromAddr, balances); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -784,18 +781,15 @@ func (bc *Blockchain) processNEP5Transfer(cache *cachedDao, tx *transaction.Tran
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !toAddr.Equals(util.Uint160{}) {
|
if !toAddr.Equals(util.Uint160{}) {
|
||||||
acc, err := cache.GetAccountStateOrNew(toAddr)
|
balances, err := cache.GetNEP5Balances(toAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
bs := acc.NEP5Balances[sc]
|
bs := balances.Trackers[sc]
|
||||||
if bs == nil {
|
|
||||||
bs = new(state.NEP5Tracker)
|
|
||||||
acc.NEP5Balances[sc] = bs
|
|
||||||
}
|
|
||||||
bs.Balance += amount
|
bs.Balance += amount
|
||||||
bs.LastUpdatedBlock = b.Index
|
bs.LastUpdatedBlock = b.Index
|
||||||
if err := cache.PutAccountState(acc); err != nil {
|
balances.Trackers[sc] = bs
|
||||||
|
if err := cache.PutNEP5Balances(toAddr, balances); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -815,6 +809,15 @@ func (bc *Blockchain) GetNEP5TransferLog(acc util.Uint160) *state.NEP5TransferLo
|
||||||
return lg
|
return lg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetNEP5Balances returns NEP5 balances for the acc.
|
||||||
|
func (bc *Blockchain) GetNEP5Balances(acc util.Uint160) *state.NEP5Balances {
|
||||||
|
bs, err := bc.dao.GetNEP5Balances(acc)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return bs
|
||||||
|
}
|
||||||
|
|
||||||
// LastBatch returns last persisted storage batch.
|
// LastBatch returns last persisted storage batch.
|
||||||
func (bc *Blockchain) LastBatch() *storage.MemBatch {
|
func (bc *Blockchain) LastBatch() *storage.MemBatch {
|
||||||
return bc.lastBatch
|
return bc.lastBatch
|
||||||
|
|
|
@ -36,6 +36,7 @@ type Blockchainer interface {
|
||||||
GetAccountState(util.Uint160) *state.Account
|
GetAccountState(util.Uint160) *state.Account
|
||||||
GetAppExecResult(util.Uint256) (*state.AppExecResult, error)
|
GetAppExecResult(util.Uint256) (*state.AppExecResult, error)
|
||||||
GetNEP5TransferLog(util.Uint160) *state.NEP5TransferLog
|
GetNEP5TransferLog(util.Uint160) *state.NEP5TransferLog
|
||||||
|
GetNEP5Balances(util.Uint160) *state.NEP5Balances
|
||||||
GetValidators(txes ...*transaction.Transaction) ([]*keys.PublicKey, error)
|
GetValidators(txes ...*transaction.Transaction) ([]*keys.PublicKey, error)
|
||||||
GetScriptHashesForVerifying(*transaction.Transaction) ([]util.Uint160, error)
|
GetScriptHashesForVerifying(*transaction.Transaction) ([]util.Uint160, error)
|
||||||
GetStorageItem(scripthash util.Uint160, key []byte) *state.StorageItem
|
GetStorageItem(scripthash util.Uint160, key []byte) *state.StorageItem
|
||||||
|
|
|
@ -135,6 +135,27 @@ func (dao *dao) DeleteContractState(hash util.Uint160) error {
|
||||||
|
|
||||||
// -- end contracts.
|
// -- end contracts.
|
||||||
|
|
||||||
|
// -- start nep5 balances.
|
||||||
|
|
||||||
|
// GetNEP5Balances retrieves nep5 balances from the cache.
|
||||||
|
func (dao *dao) GetNEP5Balances(acc util.Uint160) (*state.NEP5Balances, error) {
|
||||||
|
key := storage.AppendPrefix(storage.STNEP5Balances, acc.BytesBE())
|
||||||
|
bs := state.NewNEP5Balances()
|
||||||
|
err := dao.GetAndDecode(bs, key)
|
||||||
|
if err != nil && err != storage.ErrKeyNotFound {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNEP5Balances saves nep5 balances from the cache.
|
||||||
|
func (dao *dao) PutNEP5Balances(acc util.Uint160, bs *state.NEP5Balances) error {
|
||||||
|
key := storage.AppendPrefix(storage.STNEP5Balances, acc.BytesBE())
|
||||||
|
return dao.Put(bs, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- end nep5 balances.
|
||||||
|
|
||||||
// -- start transfer log.
|
// -- start transfer log.
|
||||||
|
|
||||||
// GetNEP5TransferLog retrieves transfer log from the cache.
|
// GetNEP5TransferLog retrieves transfer log from the cache.
|
||||||
|
|
|
@ -35,9 +35,6 @@ type Account struct {
|
||||||
Votes []*keys.PublicKey
|
Votes []*keys.PublicKey
|
||||||
Balances map[util.Uint256][]UnspentBalance
|
Balances map[util.Uint256][]UnspentBalance
|
||||||
Unclaimed []UnclaimedBalance
|
Unclaimed []UnclaimedBalance
|
||||||
// NEP5Balances is a map of the NEP5 contract hashes
|
|
||||||
// to the corresponding structures.
|
|
||||||
NEP5Balances map[util.Uint160]*NEP5Tracker
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAccount returns a new Account object.
|
// NewAccount returns a new Account object.
|
||||||
|
@ -49,8 +46,6 @@ func NewAccount(scriptHash util.Uint160) *Account {
|
||||||
Votes: []*keys.PublicKey{},
|
Votes: []*keys.PublicKey{},
|
||||||
Balances: make(map[util.Uint256][]UnspentBalance),
|
Balances: make(map[util.Uint256][]UnspentBalance),
|
||||||
Unclaimed: []UnclaimedBalance{},
|
Unclaimed: []UnclaimedBalance{},
|
||||||
|
|
||||||
NEP5Balances: make(map[util.Uint160]*NEP5Tracker),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,16 +70,6 @@ func (s *Account) DecodeBinary(br *io.BinReader) {
|
||||||
}
|
}
|
||||||
|
|
||||||
br.ReadArray(&s.Unclaimed)
|
br.ReadArray(&s.Unclaimed)
|
||||||
|
|
||||||
lenBalances = br.ReadVarUint()
|
|
||||||
s.NEP5Balances = make(map[util.Uint160]*NEP5Tracker, lenBalances)
|
|
||||||
for i := 0; i < int(lenBalances); i++ {
|
|
||||||
var key util.Uint160
|
|
||||||
var tr NEP5Tracker
|
|
||||||
br.ReadBytes(key[:])
|
|
||||||
tr.DecodeBinary(br)
|
|
||||||
s.NEP5Balances[key] = &tr
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeBinary encodes Account to the given BinWriter.
|
// EncodeBinary encodes Account to the given BinWriter.
|
||||||
|
@ -104,12 +89,6 @@ func (s *Account) EncodeBinary(bw *io.BinWriter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bw.WriteArray(s.Unclaimed)
|
bw.WriteArray(s.Unclaimed)
|
||||||
|
|
||||||
bw.WriteVarUint(uint64(len(s.NEP5Balances)))
|
|
||||||
for k, v := range s.NEP5Balances {
|
|
||||||
bw.WriteBytes(k[:])
|
|
||||||
v.EncodeBinary(bw)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeBinary implements io.Serializable interface.
|
// DecodeBinary implements io.Serializable interface.
|
||||||
|
|
|
@ -41,6 +41,42 @@ type NEP5Transfer struct {
|
||||||
Tx util.Uint256
|
Tx util.Uint256
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NEP5Balances is a map of the NEP5 contract hashes
|
||||||
|
// to the corresponding structures.
|
||||||
|
type NEP5Balances struct {
|
||||||
|
Trackers map[util.Uint160]NEP5Tracker
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNEP5Balances returns new NEP5Balances.
|
||||||
|
func NewNEP5Balances() *NEP5Balances {
|
||||||
|
return &NEP5Balances{
|
||||||
|
Trackers: make(map[util.Uint160]NEP5Tracker),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeBinary implements io.Serializable interface.
|
||||||
|
func (bs *NEP5Balances) DecodeBinary(r *io.BinReader) {
|
||||||
|
lenBalances := r.ReadVarUint()
|
||||||
|
m := make(map[util.Uint160]NEP5Tracker, lenBalances)
|
||||||
|
for i := 0; i < int(lenBalances); i++ {
|
||||||
|
var key util.Uint160
|
||||||
|
var tr NEP5Tracker
|
||||||
|
r.ReadBytes(key[:])
|
||||||
|
tr.DecodeBinary(r)
|
||||||
|
m[key] = tr
|
||||||
|
}
|
||||||
|
bs.Trackers = m
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeBinary implements io.Serializable interface.
|
||||||
|
func (bs *NEP5Balances) EncodeBinary(w *io.BinWriter) {
|
||||||
|
w.WriteVarUint(uint64(len(bs.Trackers)))
|
||||||
|
for k, v := range bs.Trackers {
|
||||||
|
w.WriteBytes(k[:])
|
||||||
|
v.EncodeBinary(w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Append appends single transfer to a log.
|
// Append appends single transfer to a log.
|
||||||
func (lg *NEP5TransferLog) Append(tr *NEP5Transfer) error {
|
func (lg *NEP5TransferLog) Append(tr *NEP5Transfer) error {
|
||||||
w := io.NewBufBinWriter()
|
w := io.NewBufBinWriter()
|
||||||
|
|
|
@ -18,6 +18,7 @@ const (
|
||||||
STContract KeyPrefix = 0x50
|
STContract KeyPrefix = 0x50
|
||||||
STStorage KeyPrefix = 0x70
|
STStorage KeyPrefix = 0x70
|
||||||
STNEP5Transfers KeyPrefix = 0x72
|
STNEP5Transfers KeyPrefix = 0x72
|
||||||
|
STNEP5Balances KeyPrefix = 0x73
|
||||||
IXHeaderHashList KeyPrefix = 0x80
|
IXHeaderHashList KeyPrefix = 0x80
|
||||||
IXValidatorsCount KeyPrefix = 0x90
|
IXValidatorsCount KeyPrefix = 0x90
|
||||||
SYSCurrentBlock KeyPrefix = 0xc0
|
SYSCurrentBlock KeyPrefix = 0xc0
|
||||||
|
|
|
@ -94,6 +94,9 @@ func (chain testChain) GetAccountState(util.Uint160) *state.Account {
|
||||||
func (chain testChain) GetNEP5TransferLog(util.Uint160) *state.NEP5TransferLog {
|
func (chain testChain) GetNEP5TransferLog(util.Uint160) *state.NEP5TransferLog {
|
||||||
panic("TODO")
|
panic("TODO")
|
||||||
}
|
}
|
||||||
|
func (chain testChain) GetNEP5Balances(util.Uint160) *state.NEP5Balances {
|
||||||
|
panic("TODO")
|
||||||
|
}
|
||||||
func (chain testChain) GetValidators(...*transaction.Transaction) ([]*keys.PublicKey, error) {
|
func (chain testChain) GetValidators(...*transaction.Transaction) ([]*keys.PublicKey, error) {
|
||||||
panic("TODO")
|
panic("TODO")
|
||||||
}
|
}
|
||||||
|
|
|
@ -423,14 +423,14 @@ func (s *Server) getNEP5Balances(ps request.Params) (interface{}, error) {
|
||||||
return nil, response.ErrInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
}
|
}
|
||||||
|
|
||||||
as := s.chain.GetAccountState(u)
|
as := s.chain.GetNEP5Balances(u)
|
||||||
bs := &result.NEP5Balances{
|
bs := &result.NEP5Balances{
|
||||||
Address: address.Uint160ToString(u),
|
Address: address.Uint160ToString(u),
|
||||||
Balances: []result.NEP5Balance{},
|
Balances: []result.NEP5Balance{},
|
||||||
}
|
}
|
||||||
if as != nil {
|
if as != nil {
|
||||||
cache := make(map[util.Uint160]int64)
|
cache := make(map[util.Uint160]int64)
|
||||||
for h, bal := range as.NEP5Balances {
|
for h, bal := range as.Trackers {
|
||||||
dec, err := s.getDecimals(h, cache)
|
dec, err := s.getDecimals(h, cache)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
|
|
Loading…
Reference in a new issue