mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-29 23:33:37 +00:00
core: implement UnclaimedBalance tracking
To make it easy to get unclaimed coins for the specified account they must be tracked together.
This commit is contained in:
parent
7095ec6c51
commit
95d9f36c98
2 changed files with 73 additions and 1 deletions
|
@ -29,7 +29,7 @@ import (
|
||||||
// Tuning parameters.
|
// Tuning parameters.
|
||||||
const (
|
const (
|
||||||
headerBatchCount = 2000
|
headerBatchCount = 2000
|
||||||
version = "0.0.3"
|
version = "0.0.4"
|
||||||
|
|
||||||
// This one comes from C# code and it's different from the constant used
|
// This one comes from C# code and it's different from the constant used
|
||||||
// when creating an asset with Neo.Asset.Create interop call. It looks
|
// when creating an asset with Neo.Asset.Create interop call. It looks
|
||||||
|
@ -479,6 +479,13 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if prevTXOutput.AssetID.Equals(GoverningTokenID()) {
|
if prevTXOutput.AssetID.Equals(GoverningTokenID()) {
|
||||||
|
account.Unclaimed = append(account.Unclaimed, state.UnclaimedBalance{
|
||||||
|
Tx: prevTX.Hash(),
|
||||||
|
Index: input.PrevIndex,
|
||||||
|
Start: prevTXHeight,
|
||||||
|
End: block.Index,
|
||||||
|
Value: prevTXOutput.Amount,
|
||||||
|
})
|
||||||
spentCoin.items[input.PrevIndex] = block.Index
|
spentCoin.items[input.PrevIndex] = block.Index
|
||||||
if err = processTXWithValidatorsSubtract(&prevTXOutput, account, cache); err != nil {
|
if err = processTXWithValidatorsSubtract(&prevTXOutput, account, cache); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -570,6 +577,37 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prevTx, _, err := cache.GetTransaction(input.PrevHash)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if int(input.PrevIndex) > len(prevTx.Outputs) {
|
||||||
|
return errors.New("invalid input in claim")
|
||||||
|
}
|
||||||
|
acc, err := cache.GetAccountState(prevTx.Outputs[input.PrevIndex].ScriptHash)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var changed bool
|
||||||
|
for i := range acc.Unclaimed {
|
||||||
|
if acc.Unclaimed[i].Tx == input.PrevHash && acc.Unclaimed[i].Index == input.PrevIndex {
|
||||||
|
copy(acc.Unclaimed[i:], acc.Unclaimed[i+1:])
|
||||||
|
acc.Unclaimed = acc.Unclaimed[:len(acc.Unclaimed)-1]
|
||||||
|
changed = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !changed {
|
||||||
|
bc.log.Warn("no spent coin in the account",
|
||||||
|
zap.String("tx", tx.Hash().StringLE()),
|
||||||
|
zap.String("input", input.PrevHash.StringLE()),
|
||||||
|
zap.String("account", acc.ScriptHash.String()))
|
||||||
|
} else if err := cache.PutAccountState(acc); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
delete(scs.items, input.PrevIndex)
|
delete(scs.items, input.PrevIndex)
|
||||||
if len(scs.items) > 0 {
|
if len(scs.items) > 0 {
|
||||||
if err = cache.PutSpentCoinState(input.PrevHash, scs); err != nil {
|
if err = cache.PutSpentCoinState(input.PrevHash, scs); err != nil {
|
||||||
|
|
|
@ -14,6 +14,16 @@ type UnspentBalance struct {
|
||||||
Value util.Fixed8 `json:"value"`
|
Value util.Fixed8 `json:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnclaimedBalance represents transaction output which was spent and
|
||||||
|
// can be claimed.
|
||||||
|
type UnclaimedBalance struct {
|
||||||
|
Tx util.Uint256
|
||||||
|
Index uint16
|
||||||
|
Start uint32
|
||||||
|
End uint32
|
||||||
|
Value util.Fixed8
|
||||||
|
}
|
||||||
|
|
||||||
// UnspentBalances is a slice of UnspentBalance (mostly needed to sort them).
|
// UnspentBalances is a slice of UnspentBalance (mostly needed to sort them).
|
||||||
type UnspentBalances []UnspentBalance
|
type UnspentBalances []UnspentBalance
|
||||||
|
|
||||||
|
@ -24,6 +34,7 @@ type Account struct {
|
||||||
IsFrozen bool
|
IsFrozen bool
|
||||||
Votes []*keys.PublicKey
|
Votes []*keys.PublicKey
|
||||||
Balances map[util.Uint256][]UnspentBalance
|
Balances map[util.Uint256][]UnspentBalance
|
||||||
|
Unclaimed []UnclaimedBalance
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAccount returns a new Account object.
|
// NewAccount returns a new Account object.
|
||||||
|
@ -34,6 +45,7 @@ func NewAccount(scriptHash util.Uint160) *Account {
|
||||||
IsFrozen: false,
|
IsFrozen: false,
|
||||||
Votes: []*keys.PublicKey{},
|
Votes: []*keys.PublicKey{},
|
||||||
Balances: make(map[util.Uint256][]UnspentBalance),
|
Balances: make(map[util.Uint256][]UnspentBalance),
|
||||||
|
Unclaimed: []UnclaimedBalance{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +68,8 @@ func (s *Account) DecodeBinary(br *io.BinReader) {
|
||||||
}
|
}
|
||||||
s.Balances[key] = ubs
|
s.Balances[key] = ubs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
br.ReadArray(&s.Unclaimed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeBinary encodes Account to the given BinWriter.
|
// EncodeBinary encodes Account to the given BinWriter.
|
||||||
|
@ -73,6 +87,8 @@ func (s *Account) EncodeBinary(bw *io.BinWriter) {
|
||||||
v[i].EncodeBinary(bw)
|
v[i].EncodeBinary(bw)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bw.WriteArray(s.Unclaimed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeBinary implements io.Serializable interface.
|
// DecodeBinary implements io.Serializable interface.
|
||||||
|
@ -89,6 +105,24 @@ func (u *UnspentBalance) EncodeBinary(w *io.BinWriter) {
|
||||||
u.Value.EncodeBinary(w)
|
u.Value.EncodeBinary(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeBinary implements io.Serializable interface.
|
||||||
|
func (u *UnclaimedBalance) DecodeBinary(r *io.BinReader) {
|
||||||
|
u.Tx.DecodeBinary(r)
|
||||||
|
u.Index = r.ReadU16LE()
|
||||||
|
u.Start = r.ReadU32LE()
|
||||||
|
u.End = r.ReadU32LE()
|
||||||
|
u.Value.DecodeBinary(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeBinary implements io.Serializable interface.
|
||||||
|
func (u *UnclaimedBalance) EncodeBinary(w *io.BinWriter) {
|
||||||
|
u.Tx.EncodeBinary(w)
|
||||||
|
w.WriteU16LE(u.Index)
|
||||||
|
w.WriteU32LE(u.Start)
|
||||||
|
w.WriteU32LE(u.End)
|
||||||
|
u.Value.EncodeBinary(w)
|
||||||
|
}
|
||||||
|
|
||||||
// GetBalanceValues sums all unspent outputs and returns a map of asset IDs to
|
// GetBalanceValues sums all unspent outputs and returns a map of asset IDs to
|
||||||
// overall balances.
|
// overall balances.
|
||||||
func (s *Account) GetBalanceValues() map[util.Uint256]util.Fixed8 {
|
func (s *Account) GetBalanceValues() map[util.Uint256]util.Fixed8 {
|
||||||
|
|
Loading…
Reference in a new issue