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.
|
||||
const (
|
||||
headerBatchCount = 2000
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
|
||||
// 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
|
||||
|
@ -479,6 +479,13 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
|
|||
}
|
||||
|
||||
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
|
||||
if err = processTXWithValidatorsSubtract(&prevTXOutput, account, cache); err != nil {
|
||||
return err
|
||||
|
@ -570,6 +577,37 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
|
|||
}
|
||||
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)
|
||||
if len(scs.items) > 0 {
|
||||
if err = cache.PutSpentCoinState(input.PrevHash, scs); err != nil {
|
||||
|
|
|
@ -14,6 +14,16 @@ type UnspentBalance struct {
|
|||
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).
|
||||
type UnspentBalances []UnspentBalance
|
||||
|
||||
|
@ -24,6 +34,7 @@ type Account struct {
|
|||
IsFrozen bool
|
||||
Votes []*keys.PublicKey
|
||||
Balances map[util.Uint256][]UnspentBalance
|
||||
Unclaimed []UnclaimedBalance
|
||||
}
|
||||
|
||||
// NewAccount returns a new Account object.
|
||||
|
@ -34,6 +45,7 @@ func NewAccount(scriptHash util.Uint160) *Account {
|
|||
IsFrozen: false,
|
||||
Votes: []*keys.PublicKey{},
|
||||
Balances: make(map[util.Uint256][]UnspentBalance),
|
||||
Unclaimed: []UnclaimedBalance{},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,6 +68,8 @@ func (s *Account) DecodeBinary(br *io.BinReader) {
|
|||
}
|
||||
s.Balances[key] = ubs
|
||||
}
|
||||
|
||||
br.ReadArray(&s.Unclaimed)
|
||||
}
|
||||
|
||||
// EncodeBinary encodes Account to the given BinWriter.
|
||||
|
@ -73,6 +87,8 @@ func (s *Account) EncodeBinary(bw *io.BinWriter) {
|
|||
v[i].EncodeBinary(bw)
|
||||
}
|
||||
}
|
||||
|
||||
bw.WriteArray(s.Unclaimed)
|
||||
}
|
||||
|
||||
// DecodeBinary implements io.Serializable interface.
|
||||
|
@ -89,6 +105,24 @@ func (u *UnspentBalance) EncodeBinary(w *io.BinWriter) {
|
|||
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
|
||||
// overall balances.
|
||||
func (s *Account) GetBalanceValues() map[util.Uint256]util.Fixed8 {
|
||||
|
|
Loading…
Reference in a new issue