forked from TrueCloudLab/neoneo-go
core: move (un)SpentCoin structs into the state package
As they're all about the state.
This commit is contained in:
parent
0e2bda4f21
commit
377fb382aa
13 changed files with 155 additions and 161 deletions
|
@ -475,7 +475,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cache.PutUnspentCoinState(tx.Hash(), NewUnspentCoinState(len(tx.Outputs))); err != nil {
|
if err := cache.PutUnspentCoinState(tx.Hash(), state.NewUnspentCoin(len(tx.Outputs))); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,9 +499,9 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
oldSpentCoinLen := len(spentCoin.items)
|
oldSpentCoinLen := len(spentCoin.Items)
|
||||||
for _, input := range inputs {
|
for _, input := range inputs {
|
||||||
unspent.states[input.PrevIndex] = state.CoinSpent
|
unspent.States[input.PrevIndex] = state.CoinSpent
|
||||||
prevTXOutput := prevTX.Outputs[input.PrevIndex]
|
prevTXOutput := prevTX.Outputs[input.PrevIndex]
|
||||||
account, err := cache.GetAccountStateOrNew(prevTXOutput.ScriptHash)
|
account, err := cache.GetAccountStateOrNew(prevTXOutput.ScriptHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -516,7 +516,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
|
||||||
End: block.Index,
|
End: block.Index,
|
||||||
Value: prevTXOutput.Amount,
|
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
|
||||||
}
|
}
|
||||||
|
@ -548,7 +548,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
|
||||||
if err = cache.PutUnspentCoinState(prevHash, unspent); err != nil {
|
if err = cache.PutUnspentCoinState(prevHash, unspent); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if oldSpentCoinLen != len(spentCoin.items) {
|
if oldSpentCoinLen != len(spentCoin.Items) {
|
||||||
if err = cache.PutSpentCoinState(prevHash, spentCoin); err != nil {
|
if err = cache.PutSpentCoinState(prevHash, spentCoin); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -590,7 +590,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
|
||||||
for _, input := range t.Claims {
|
for _, input := range t.Claims {
|
||||||
scs, err := cache.GetSpentCoinState(input.PrevHash)
|
scs, err := cache.GetSpentCoinState(input.PrevHash)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
_, ok := scs.items[input.PrevIndex]
|
_, ok := scs.Items[input.PrevIndex]
|
||||||
if !ok {
|
if !ok {
|
||||||
err = errors.New("no spent coin state")
|
err = errors.New("no spent coin state")
|
||||||
}
|
}
|
||||||
|
@ -644,8 +644,8 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
|
||||||
return err
|
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 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1174,7 +1174,7 @@ func (bc *Blockchain) GetAccountState(scriptHash util.Uint160) *state.Account {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUnspentCoinState returns unspent coin state for given tx hash.
|
// GetUnspentCoinState returns unspent coin state for given tx hash.
|
||||||
func (bc *Blockchain) GetUnspentCoinState(hash util.Uint256) *UnspentCoinState {
|
func (bc *Blockchain) GetUnspentCoinState(hash util.Uint256) *state.UnspentCoin {
|
||||||
ucs, err := bc.dao.GetUnspentCoinState(hash)
|
ucs, err := bc.dao.GetUnspentCoinState(hash)
|
||||||
if ucs == nil && err != storage.ErrKeyNotFound {
|
if ucs == nil && err != storage.ErrKeyNotFound {
|
||||||
bc.log.Warn("failed to get unspent coin state", zap.Error(err))
|
bc.log.Warn("failed to get unspent coin state", zap.Error(err))
|
||||||
|
@ -1472,7 +1472,7 @@ func (bc *Blockchain) getUnclaimed(h util.Uint256) (map[uint16]*spentCoin, error
|
||||||
}
|
}
|
||||||
|
|
||||||
result := make(map[uint16]*spentCoin)
|
result := make(map[uint16]*spentCoin)
|
||||||
for i, height := range scs.items {
|
for i, height := range scs.Items {
|
||||||
result[i] = &spentCoin{
|
result[i] = &spentCoin{
|
||||||
Output: &tx.Outputs[i],
|
Output: &tx.Outputs[i],
|
||||||
StartHeight: txHeight,
|
StartHeight: txHeight,
|
||||||
|
|
|
@ -41,7 +41,7 @@ type Blockchainer interface {
|
||||||
GetStorageItems(hash util.Uint160) (map[string]*state.StorageItem, error)
|
GetStorageItems(hash util.Uint160) (map[string]*state.StorageItem, error)
|
||||||
GetTestVM() (*vm.VM, storage.Store)
|
GetTestVM() (*vm.VM, storage.Store)
|
||||||
GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error)
|
GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error)
|
||||||
GetUnspentCoinState(util.Uint256) *UnspentCoinState
|
GetUnspentCoinState(util.Uint256) *state.UnspentCoin
|
||||||
References(t *transaction.Transaction) ([]transaction.InOut, error)
|
References(t *transaction.Transaction) ([]transaction.InOut, error)
|
||||||
mempool.Feer // fee interface
|
mempool.Feer // fee interface
|
||||||
PoolTx(*transaction.Transaction) error
|
PoolTx(*transaction.Transaction) error
|
||||||
|
|
|
@ -178,22 +178,20 @@ func (dao *dao) AppendNEP5Transfer(acc util.Uint160, tr *state.NEP5Transfer) err
|
||||||
// GetUnspentCoinStateOrNew gets UnspentCoinState from temporary or persistent Store
|
// GetUnspentCoinStateOrNew gets UnspentCoinState from temporary or persistent Store
|
||||||
// and return it. If it's not present in both stores, returns a new
|
// and return it. If it's not present in both stores, returns a new
|
||||||
// UnspentCoinState.
|
// UnspentCoinState.
|
||||||
func (dao *dao) GetUnspentCoinStateOrNew(hash util.Uint256) (*UnspentCoinState, error) {
|
func (dao *dao) GetUnspentCoinStateOrNew(hash util.Uint256) (*state.UnspentCoin, error) {
|
||||||
unspent, err := dao.GetUnspentCoinState(hash)
|
unspent, err := dao.GetUnspentCoinState(hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != storage.ErrKeyNotFound {
|
if err != storage.ErrKeyNotFound {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
unspent = &UnspentCoinState{
|
unspent = state.NewUnspentCoin(0)
|
||||||
states: []state.Coin{},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return unspent, nil
|
return unspent, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUnspentCoinState retrieves UnspentCoinState from the given store.
|
// GetUnspentCoinState retrieves UnspentCoinState from the given store.
|
||||||
func (dao *dao) GetUnspentCoinState(hash util.Uint256) (*UnspentCoinState, error) {
|
func (dao *dao) GetUnspentCoinState(hash util.Uint256) (*state.UnspentCoin, error) {
|
||||||
unspent := &UnspentCoinState{}
|
unspent := &state.UnspentCoin{}
|
||||||
key := storage.AppendPrefix(storage.STCoin, hash.BytesLE())
|
key := storage.AppendPrefix(storage.STCoin, hash.BytesLE())
|
||||||
err := dao.GetAndDecode(unspent, key)
|
err := dao.GetAndDecode(unspent, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -203,7 +201,7 @@ func (dao *dao) GetUnspentCoinState(hash util.Uint256) (*UnspentCoinState, error
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutUnspentCoinState puts given UnspentCoinState into the given store.
|
// PutUnspentCoinState puts given UnspentCoinState into the given store.
|
||||||
func (dao *dao) PutUnspentCoinState(hash util.Uint256, ucs *UnspentCoinState) error {
|
func (dao *dao) PutUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin) error {
|
||||||
key := storage.AppendPrefix(storage.STCoin, hash.BytesLE())
|
key := storage.AppendPrefix(storage.STCoin, hash.BytesLE())
|
||||||
return dao.Put(ucs, key)
|
return dao.Put(ucs, key)
|
||||||
}
|
}
|
||||||
|
@ -213,20 +211,20 @@ func (dao *dao) PutUnspentCoinState(hash util.Uint256, ucs *UnspentCoinState) er
|
||||||
// -- start spent coins.
|
// -- start spent coins.
|
||||||
|
|
||||||
// GetSpentCoinsOrNew returns spent coins from store.
|
// GetSpentCoinsOrNew returns spent coins from store.
|
||||||
func (dao *dao) GetSpentCoinsOrNew(hash util.Uint256, height uint32) (*SpentCoinState, error) {
|
func (dao *dao) GetSpentCoinsOrNew(hash util.Uint256, height uint32) (*state.SpentCoin, error) {
|
||||||
spent, err := dao.GetSpentCoinState(hash)
|
spent, err := dao.GetSpentCoinState(hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != storage.ErrKeyNotFound {
|
if err != storage.ErrKeyNotFound {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
spent = NewSpentCoinState(height)
|
spent = state.NewSpentCoin(height)
|
||||||
}
|
}
|
||||||
return spent, nil
|
return spent, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSpentCoinState gets SpentCoinState from the given store.
|
// GetSpentCoinState gets SpentCoinState from the given store.
|
||||||
func (dao *dao) GetSpentCoinState(hash util.Uint256) (*SpentCoinState, error) {
|
func (dao *dao) GetSpentCoinState(hash util.Uint256) (*state.SpentCoin, error) {
|
||||||
spent := &SpentCoinState{}
|
spent := &state.SpentCoin{}
|
||||||
key := storage.AppendPrefix(storage.STSpentCoin, hash.BytesLE())
|
key := storage.AppendPrefix(storage.STSpentCoin, hash.BytesLE())
|
||||||
err := dao.GetAndDecode(spent, key)
|
err := dao.GetAndDecode(spent, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -236,7 +234,7 @@ func (dao *dao) GetSpentCoinState(hash util.Uint256) (*SpentCoinState, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutSpentCoinState puts given SpentCoinState into the given store.
|
// PutSpentCoinState puts given SpentCoinState into the given store.
|
||||||
func (dao *dao) PutSpentCoinState(hash util.Uint256, scs *SpentCoinState) error {
|
func (dao *dao) PutSpentCoinState(hash util.Uint256, scs *state.SpentCoin) error {
|
||||||
key := storage.AppendPrefix(storage.STSpentCoin, hash.BytesLE())
|
key := storage.AppendPrefix(storage.STSpentCoin, hash.BytesLE())
|
||||||
return dao.Put(scs, key)
|
return dao.Put(scs, key)
|
||||||
}
|
}
|
||||||
|
@ -592,7 +590,7 @@ func (dao *dao) IsDoubleSpend(tx *transaction.Transaction) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, input := range inputs {
|
for _, input := range inputs {
|
||||||
if int(input.PrevIndex) >= len(unspent.states) || unspent.states[input.PrevIndex] == state.CoinSpent {
|
if int(input.PrevIndex) >= len(unspent.States) || unspent.States[input.PrevIndex] == state.CoinSpent {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -612,7 +610,7 @@ func (dao *dao) IsDoubleClaim(claim *transaction.ClaimTX) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
for _, input := range inputs {
|
for _, input := range inputs {
|
||||||
_, ok := scs.items[input.PrevIndex]
|
_, ok := scs.Items[input.PrevIndex]
|
||||||
if !ok {
|
if !ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,7 +113,7 @@ func TestGetUnspentCoinState_Err(t *testing.T) {
|
||||||
func TestPutGetUnspentCoinState(t *testing.T) {
|
func TestPutGetUnspentCoinState(t *testing.T) {
|
||||||
dao := newDao(storage.NewMemoryStore())
|
dao := newDao(storage.NewMemoryStore())
|
||||||
hash := random.Uint256()
|
hash := random.Uint256()
|
||||||
unspentCoinState := &UnspentCoinState{states: []state.Coin{}}
|
unspentCoinState := &state.UnspentCoin{States: []state.Coin{}}
|
||||||
err := dao.PutUnspentCoinState(hash, unspentCoinState)
|
err := dao.PutUnspentCoinState(hash, unspentCoinState)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
gotUnspentCoinState, err := dao.GetUnspentCoinState(hash)
|
gotUnspentCoinState, err := dao.GetUnspentCoinState(hash)
|
||||||
|
@ -132,7 +132,7 @@ func TestGetSpentCoinStateOrNew_New(t *testing.T) {
|
||||||
func TestPutAndGetSpentCoinState(t *testing.T) {
|
func TestPutAndGetSpentCoinState(t *testing.T) {
|
||||||
dao := newDao(storage.NewMemoryStore())
|
dao := newDao(storage.NewMemoryStore())
|
||||||
hash := random.Uint256()
|
hash := random.Uint256()
|
||||||
spentCoinState := &SpentCoinState{items: make(map[uint16]uint32)}
|
spentCoinState := &state.SpentCoin{Items: make(map[uint16]uint32)}
|
||||||
err := dao.PutSpentCoinState(hash, spentCoinState)
|
err := dao.PutSpentCoinState(hash, spentCoinState)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
gotSpentCoinState, err := dao.GetSpentCoinState(hash)
|
gotSpentCoinState, err := dao.GetSpentCoinState(hash)
|
||||||
|
@ -151,7 +151,7 @@ func TestGetSpentCoinState_Err(t *testing.T) {
|
||||||
func TestDeleteSpentCoinState(t *testing.T) {
|
func TestDeleteSpentCoinState(t *testing.T) {
|
||||||
dao := newDao(storage.NewMemoryStore())
|
dao := newDao(storage.NewMemoryStore())
|
||||||
hash := random.Uint256()
|
hash := random.Uint256()
|
||||||
spentCoinState := &SpentCoinState{items: make(map[uint16]uint32)}
|
spentCoinState := &state.SpentCoin{Items: make(map[uint16]uint32)}
|
||||||
err := dao.PutSpentCoinState(hash, spentCoinState)
|
err := dao.PutSpentCoinState(hash, spentCoinState)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = dao.DeleteSpentCoinState(hash)
|
err = dao.DeleteSpentCoinState(hash)
|
||||||
|
|
10
pkg/core/spent_coin.go
Normal file
10
pkg/core/spent_coin.go
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
|
|
||||||
|
// spentCoin represents the state of a single spent coin output.
|
||||||
|
type spentCoin struct {
|
||||||
|
Output *transaction.Output
|
||||||
|
StartHeight uint32
|
||||||
|
EndHeight uint32
|
||||||
|
}
|
|
@ -1,56 +0,0 @@
|
||||||
package core
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SpentCoinState represents the state of a spent coin.
|
|
||||||
type SpentCoinState struct {
|
|
||||||
txHeight uint32
|
|
||||||
|
|
||||||
// A mapping between the index of the prevIndex and block height.
|
|
||||||
items map[uint16]uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
// spentCoin represents the state of a single spent coin output.
|
|
||||||
type spentCoin struct {
|
|
||||||
Output *transaction.Output
|
|
||||||
StartHeight uint32
|
|
||||||
EndHeight uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSpentCoinState returns a new SpentCoinState object.
|
|
||||||
func NewSpentCoinState(height uint32) *SpentCoinState {
|
|
||||||
return &SpentCoinState{
|
|
||||||
txHeight: height,
|
|
||||||
items: make(map[uint16]uint32),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeBinary implements Serializable interface.
|
|
||||||
func (s *SpentCoinState) DecodeBinary(br *io.BinReader) {
|
|
||||||
s.txHeight = br.ReadU32LE()
|
|
||||||
|
|
||||||
s.items = make(map[uint16]uint32)
|
|
||||||
lenItems := br.ReadVarUint()
|
|
||||||
for i := 0; i < int(lenItems); i++ {
|
|
||||||
var (
|
|
||||||
key uint16
|
|
||||||
value uint32
|
|
||||||
)
|
|
||||||
key = br.ReadU16LE()
|
|
||||||
value = br.ReadU32LE()
|
|
||||||
s.items[key] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeBinary implements Serializable interface.
|
|
||||||
func (s *SpentCoinState) EncodeBinary(bw *io.BinWriter) {
|
|
||||||
bw.WriteU32LE(s.txHeight)
|
|
||||||
bw.WriteVarUint(uint64(len(s.items)))
|
|
||||||
for k, v := range s.items {
|
|
||||||
bw.WriteU16LE(k)
|
|
||||||
bw.WriteU32LE(v)
|
|
||||||
}
|
|
||||||
}
|
|
46
pkg/core/state/spent_coin.go
Normal file
46
pkg/core/state/spent_coin.go
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
package state
|
||||||
|
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
|
|
||||||
|
// SpentCoin represents the state of a spent coin.
|
||||||
|
type SpentCoin struct {
|
||||||
|
TxHeight uint32
|
||||||
|
|
||||||
|
// A mapping between the index of the prevIndex and block height.
|
||||||
|
Items map[uint16]uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSpentCoin returns a new SpentCoin object.
|
||||||
|
func NewSpentCoin(height uint32) *SpentCoin {
|
||||||
|
return &SpentCoin{
|
||||||
|
TxHeight: height,
|
||||||
|
Items: make(map[uint16]uint32),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeBinary implements Serializable interface.
|
||||||
|
func (s *SpentCoin) DecodeBinary(br *io.BinReader) {
|
||||||
|
s.TxHeight = br.ReadU32LE()
|
||||||
|
|
||||||
|
s.Items = make(map[uint16]uint32)
|
||||||
|
lenItems := br.ReadVarUint()
|
||||||
|
for i := 0; i < int(lenItems); i++ {
|
||||||
|
var (
|
||||||
|
key uint16
|
||||||
|
value uint32
|
||||||
|
)
|
||||||
|
key = br.ReadU16LE()
|
||||||
|
value = br.ReadU32LE()
|
||||||
|
s.Items[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeBinary implements Serializable interface.
|
||||||
|
func (s *SpentCoin) EncodeBinary(bw *io.BinWriter) {
|
||||||
|
bw.WriteU32LE(s.TxHeight)
|
||||||
|
bw.WriteVarUint(uint64(len(s.Items)))
|
||||||
|
for k, v := range s.Items {
|
||||||
|
bw.WriteU16LE(k)
|
||||||
|
bw.WriteU32LE(v)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,17 +1,16 @@
|
||||||
package core
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/internal/random"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEncodeDecodeSpentCoinState(t *testing.T) {
|
func TestEncodeDecodeSpentCoin(t *testing.T) {
|
||||||
spent := &SpentCoinState{
|
spent := &SpentCoin{
|
||||||
txHeight: 1001,
|
TxHeight: 1001,
|
||||||
items: map[uint16]uint32{
|
Items: map[uint16]uint32{
|
||||||
1: 3,
|
1: 3,
|
||||||
2: 8,
|
2: 8,
|
||||||
4: 100,
|
4: 100,
|
||||||
|
@ -21,7 +20,7 @@ func TestEncodeDecodeSpentCoinState(t *testing.T) {
|
||||||
buf := io.NewBufBinWriter()
|
buf := io.NewBufBinWriter()
|
||||||
spent.EncodeBinary(buf.BinWriter)
|
spent.EncodeBinary(buf.BinWriter)
|
||||||
assert.Nil(t, buf.Err)
|
assert.Nil(t, buf.Err)
|
||||||
spentDecode := new(SpentCoinState)
|
spentDecode := new(SpentCoin)
|
||||||
r := io.NewBinReaderFromBuf(buf.Bytes())
|
r := io.NewBinReaderFromBuf(buf.Bytes())
|
||||||
spentDecode.DecodeBinary(r)
|
spentDecode.DecodeBinary(r)
|
||||||
assert.Nil(t, r.Err)
|
assert.Nil(t, r.Err)
|
38
pkg/core/state/unspent_coin.go
Normal file
38
pkg/core/state/unspent_coin.go
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package state
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UnspentCoin hold the state of a unspent coin.
|
||||||
|
type UnspentCoin struct {
|
||||||
|
States []Coin
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewUnspentCoin returns a new unspent coin state with N confirmed states.
|
||||||
|
func NewUnspentCoin(n int) *UnspentCoin {
|
||||||
|
u := &UnspentCoin{
|
||||||
|
States: make([]Coin, n),
|
||||||
|
}
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
u.States[i] = CoinConfirmed
|
||||||
|
}
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeBinary encodes UnspentCoin to the given BinWriter.
|
||||||
|
func (s *UnspentCoin) EncodeBinary(bw *io.BinWriter) {
|
||||||
|
bw.WriteVarUint(uint64(len(s.States)))
|
||||||
|
for _, state := range s.States {
|
||||||
|
bw.WriteB(byte(state))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeBinary decodes UnspentCoin from the given BinReader.
|
||||||
|
func (s *UnspentCoin) DecodeBinary(br *io.BinReader) {
|
||||||
|
lenStates := br.ReadVarUint()
|
||||||
|
s.States = make([]Coin, lenStates)
|
||||||
|
for i := 0; i < int(lenStates); i++ {
|
||||||
|
s.States[i] = Coin(br.ReadB())
|
||||||
|
}
|
||||||
|
}
|
28
pkg/core/state/unspent_coin_test.go
Normal file
28
pkg/core/state/unspent_coin_test.go
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package state
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDecodeEncodeUnspentCoin(t *testing.T) {
|
||||||
|
unspent := &UnspentCoin{
|
||||||
|
States: []Coin{
|
||||||
|
CoinConfirmed,
|
||||||
|
CoinSpent,
|
||||||
|
CoinSpent,
|
||||||
|
CoinSpent,
|
||||||
|
CoinConfirmed,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := io.NewBufBinWriter()
|
||||||
|
unspent.EncodeBinary(buf.BinWriter)
|
||||||
|
assert.Nil(t, buf.Err)
|
||||||
|
unspentDecode := &UnspentCoin{}
|
||||||
|
r := io.NewBinReaderFromBuf(buf.Bytes())
|
||||||
|
unspentDecode.DecodeBinary(r)
|
||||||
|
assert.Nil(t, r.Err)
|
||||||
|
}
|
|
@ -1,39 +0,0 @@
|
||||||
package core
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// UnspentCoinState hold the state of a unspent coin.
|
|
||||||
type UnspentCoinState struct {
|
|
||||||
states []state.Coin
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewUnspentCoinState returns a new unspent coin state with N confirmed states.
|
|
||||||
func NewUnspentCoinState(n int) *UnspentCoinState {
|
|
||||||
u := &UnspentCoinState{
|
|
||||||
states: make([]state.Coin, n),
|
|
||||||
}
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
u.states[i] = state.CoinConfirmed
|
|
||||||
}
|
|
||||||
return u
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeBinary encodes UnspentCoinState to the given BinWriter.
|
|
||||||
func (s *UnspentCoinState) EncodeBinary(bw *io.BinWriter) {
|
|
||||||
bw.WriteVarUint(uint64(len(s.states)))
|
|
||||||
for _, state := range s.states {
|
|
||||||
bw.WriteB(byte(state))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeBinary decodes UnspentCoinState from the given BinReader.
|
|
||||||
func (s *UnspentCoinState) DecodeBinary(br *io.BinReader) {
|
|
||||||
lenStates := br.ReadVarUint()
|
|
||||||
s.states = make([]state.Coin, lenStates)
|
|
||||||
for i := 0; i < int(lenStates); i++ {
|
|
||||||
s.states[i] = state.Coin(br.ReadB())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
package core
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDecodeEncodeUnspentCoinState(t *testing.T) {
|
|
||||||
unspent := &UnspentCoinState{
|
|
||||||
states: []state.Coin{
|
|
||||||
state.CoinConfirmed,
|
|
||||||
state.CoinSpent,
|
|
||||||
state.CoinSpent,
|
|
||||||
state.CoinSpent,
|
|
||||||
state.CoinConfirmed,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := io.NewBufBinWriter()
|
|
||||||
unspent.EncodeBinary(buf.BinWriter)
|
|
||||||
assert.Nil(t, buf.Err)
|
|
||||||
unspentDecode := &UnspentCoinState{}
|
|
||||||
r := io.NewBinReaderFromBuf(buf.Bytes())
|
|
||||||
unspentDecode.DecodeBinary(r)
|
|
||||||
assert.Nil(t, r.Err)
|
|
||||||
}
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/config"
|
"github.com/nspcc-dev/neo-go/config"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/mempool"
|
"github.com/nspcc-dev/neo-go/pkg/core/mempool"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
|
@ -126,7 +125,7 @@ func (chain testChain) GetTransaction(util.Uint256) (*transaction.Transaction, u
|
||||||
panic("TODO")
|
panic("TODO")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (chain testChain) GetUnspentCoinState(util.Uint256) *core.UnspentCoinState {
|
func (chain testChain) GetUnspentCoinState(util.Uint256) *state.UnspentCoin {
|
||||||
panic("TODO")
|
panic("TODO")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue