23464401bc
This change reduces pressure on DB by doing the following things: * not storing additional KV pair for SpentCoin * storing Output right in the UnspentCoin, thus eliminating the need to get a full transaction from DB At the same time it makes UnspentCoin more fat and hot, but it should probably worth it. Also drop `GetUnspentCoinStateOrNew` as it shouldn't ever existed, UTXOs can't come out of nowhere. 1.5M block import time (VerifyBlocks disabled) on AMD Ryzen 5 1600/16GB/HDD, before: real 302m9.895s user 96m17.200s sys 13m37.084s after: real 159m16.551s user 69m58.279s sys 7m34.334s So it's almost two-fold which is a great improvement.
60 lines
1.5 KiB
Go
60 lines
1.5 KiB
Go
package state
|
|
|
|
import (
|
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
|
)
|
|
|
|
// UnspentCoin hold the state of a unspent coin.
|
|
type UnspentCoin struct {
|
|
Height uint32
|
|
States []OutputState
|
|
}
|
|
|
|
// OutputState combines transaction output (UTXO) and its state
|
|
// (spent/claimed...) along with the height of spend (if it's spent).
|
|
type OutputState struct {
|
|
transaction.Output
|
|
|
|
SpendHeight uint32
|
|
State Coin
|
|
}
|
|
|
|
// NewUnspentCoin returns a new unspent coin state with N confirmed states.
|
|
func NewUnspentCoin(height uint32, tx *transaction.Transaction) *UnspentCoin {
|
|
u := &UnspentCoin{
|
|
Height: height,
|
|
States: make([]OutputState, len(tx.Outputs)),
|
|
}
|
|
for i := range tx.Outputs {
|
|
u.States[i] = OutputState{Output: tx.Outputs[i]}
|
|
}
|
|
return u
|
|
}
|
|
|
|
// EncodeBinary encodes UnspentCoin to the given BinWriter.
|
|
func (s *UnspentCoin) EncodeBinary(bw *io.BinWriter) {
|
|
bw.WriteU32LE(s.Height)
|
|
bw.WriteArray(s.States)
|
|
bw.WriteVarUint(uint64(len(s.States)))
|
|
}
|
|
|
|
// DecodeBinary decodes UnspentCoin from the given BinReader.
|
|
func (s *UnspentCoin) DecodeBinary(br *io.BinReader) {
|
|
s.Height = br.ReadU32LE()
|
|
br.ReadArray(&s.States)
|
|
}
|
|
|
|
// EncodeBinary implements Serializable interface.
|
|
func (o *OutputState) EncodeBinary(w *io.BinWriter) {
|
|
o.Output.EncodeBinary(w)
|
|
w.WriteU32LE(o.SpendHeight)
|
|
w.WriteB(byte(o.State))
|
|
}
|
|
|
|
// DecodeBinary implements Serializable interface.
|
|
func (o *OutputState) DecodeBinary(r *io.BinReader) {
|
|
o.Output.DecodeBinary(r)
|
|
o.SpendHeight = r.ReadU32LE()
|
|
o.State = Coin(r.ReadB())
|
|
}
|