forked from TrueCloudLab/neoneo-go
core: implement StorageItem for future interops
This commit is contained in:
parent
2156d5db73
commit
bfddf9b3f6
5 changed files with 135 additions and 0 deletions
|
@ -512,6 +512,43 @@ func getTransactionFromStore(s storage.Store, hash util.Uint256) (*transaction.T
|
||||||
return tx, height, nil
|
return tx, height, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetStorageItem returns an item from storage.
|
||||||
|
func (bc *Blockchain) GetStorageItem(scripthash util.Uint160, key []byte) *StorageItem {
|
||||||
|
sItem := getStorageItemFromStore(bc.memStore, scripthash, key)
|
||||||
|
if sItem == nil {
|
||||||
|
sItem = getStorageItemFromStore(bc.Store, scripthash, key)
|
||||||
|
}
|
||||||
|
return sItem
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStorageItems returns all storage items for a given scripthash.
|
||||||
|
func (bc *Blockchain) GetStorageItems(hash util.Uint160) (map[string]*StorageItem, error) {
|
||||||
|
var siMap = make(map[string]*StorageItem)
|
||||||
|
var err error
|
||||||
|
|
||||||
|
saveToMap := func(k, v []byte) {
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r := io.NewBinReaderFromBuf(v)
|
||||||
|
si := &StorageItem{}
|
||||||
|
si.DecodeBinary(r)
|
||||||
|
if r.Err != nil {
|
||||||
|
err = r.Err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cut prefix and hash.
|
||||||
|
siMap[string(k[21:])] = si
|
||||||
|
}
|
||||||
|
bc.memStore.Seek(storage.AppendPrefix(storage.STStorage, hash.BytesReverse()), saveToMap)
|
||||||
|
bc.Store.Seek(storage.AppendPrefix(storage.STStorage, hash.BytesReverse()), saveToMap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return siMap, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetBlock returns a Block by the given hash.
|
// GetBlock returns a Block by the given hash.
|
||||||
func (bc *Blockchain) GetBlock(hash util.Uint256) (*Block, error) {
|
func (bc *Blockchain) GetBlock(hash util.Uint256) (*Block, error) {
|
||||||
block, err := getBlockFromStore(bc.memStore, hash)
|
block, err := getBlockFromStore(bc.memStore, hash)
|
||||||
|
|
|
@ -23,6 +23,8 @@ type Blockchainer interface {
|
||||||
HasTransaction(util.Uint256) bool
|
HasTransaction(util.Uint256) bool
|
||||||
GetAssetState(util.Uint256) *AssetState
|
GetAssetState(util.Uint256) *AssetState
|
||||||
GetAccountState(util.Uint160) *AccountState
|
GetAccountState(util.Uint160) *AccountState
|
||||||
|
GetStorageItem(scripthash util.Uint160, key []byte) *StorageItem
|
||||||
|
GetStorageItems(hash util.Uint160) (map[string]*StorageItem, error)
|
||||||
GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error)
|
GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error)
|
||||||
References(t *transaction.Transaction) map[transaction.Input]*transaction.Output
|
References(t *transaction.Transaction) map[transaction.Input]*transaction.Output
|
||||||
Feer // fee interface
|
Feer // fee interface
|
||||||
|
|
64
pkg/core/storage_item.go
Normal file
64
pkg/core/storage_item.go
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/CityOfZion/neo-go/pkg/core/storage"
|
||||||
|
"github.com/CityOfZion/neo-go/pkg/io"
|
||||||
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StorageItem is the value to be stored with read-only flag.
|
||||||
|
type StorageItem struct {
|
||||||
|
Value []byte
|
||||||
|
IsConst bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// makeStorageItemKey returns a key used to store StorageItem in the DB.
|
||||||
|
func makeStorageItemKey(scripthash util.Uint160, key []byte) []byte {
|
||||||
|
return storage.AppendPrefix(storage.STStorage, append(scripthash.BytesReverse(), key...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// getStorageItemFromStore returns StorageItem if it exists in the given Store.
|
||||||
|
func getStorageItemFromStore(s storage.Store, scripthash util.Uint160, key []byte) *StorageItem {
|
||||||
|
b, err := s.Get(makeStorageItemKey(scripthash, key))
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
r := io.NewBinReaderFromBuf(b)
|
||||||
|
|
||||||
|
si := &StorageItem{}
|
||||||
|
si.DecodeBinary(r)
|
||||||
|
if r.Err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return si
|
||||||
|
}
|
||||||
|
|
||||||
|
// putStorageItemIntoStore puts given StorageItem for given script with given
|
||||||
|
// key into the given Store.
|
||||||
|
func putStorageItemIntoStore(s storage.Store, scripthash util.Uint160, key []byte, si *StorageItem) error {
|
||||||
|
buf := io.NewBufBinWriter()
|
||||||
|
si.EncodeBinary(buf.BinWriter)
|
||||||
|
if buf.Err != nil {
|
||||||
|
return buf.Err
|
||||||
|
}
|
||||||
|
return s.Put(makeStorageItemKey(scripthash, key), buf.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
// deleteStorageItemInStore drops storage item for the given script with the
|
||||||
|
// given key from the Store.
|
||||||
|
func deleteStorageItemInStore(s storage.Store, scripthash util.Uint160, key []byte) error {
|
||||||
|
return s.Delete(makeStorageItemKey(scripthash, key))
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeBinary implements Serializable interface.
|
||||||
|
func (si *StorageItem) EncodeBinary(w *io.BinWriter) {
|
||||||
|
w.WriteBytes(si.Value)
|
||||||
|
w.WriteLE(si.IsConst)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeBinary implements Serializable interface.
|
||||||
|
func (si *StorageItem) DecodeBinary(r *io.BinReader) {
|
||||||
|
si.Value = r.ReadBytes()
|
||||||
|
r.ReadLE(&si.IsConst)
|
||||||
|
}
|
26
pkg/core/storage_item_test.go
Normal file
26
pkg/core/storage_item_test.go
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/CityOfZion/neo-go/pkg/core/storage"
|
||||||
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPutGetDeleteStorageItem(t *testing.T) {
|
||||||
|
s := storage.NewMemoryStore()
|
||||||
|
si := &StorageItem{
|
||||||
|
Value: []byte("smth"),
|
||||||
|
}
|
||||||
|
key := []byte("key")
|
||||||
|
cHash, err := util.Uint160DecodeBytes([]byte("abcdefghijklmnopqrst"))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NoError(t, putStorageItemIntoStore(s, cHash, key, si))
|
||||||
|
siRead := getStorageItemFromStore(s, cHash, key)
|
||||||
|
assert.NotNil(t, siRead)
|
||||||
|
assert.Equal(t, si, siRead)
|
||||||
|
assert.NoError(t, deleteStorageItemInStore(s, cHash, key))
|
||||||
|
siRead2 := getStorageItemFromStore(s, cHash, key)
|
||||||
|
assert.Nil(t, siRead2)
|
||||||
|
}
|
|
@ -69,6 +69,12 @@ func (chain testChain) GetAssetState(util.Uint256) *core.AssetState {
|
||||||
func (chain testChain) GetAccountState(util.Uint160) *core.AccountState {
|
func (chain testChain) GetAccountState(util.Uint160) *core.AccountState {
|
||||||
panic("TODO")
|
panic("TODO")
|
||||||
}
|
}
|
||||||
|
func (chain testChain) GetStorageItem(scripthash util.Uint160, key []byte) *core.StorageItem {
|
||||||
|
panic("TODO")
|
||||||
|
}
|
||||||
|
func (chain testChain) GetStorageItems(hash util.Uint160) (map[string]*core.StorageItem, error) {
|
||||||
|
panic("TODO")
|
||||||
|
}
|
||||||
func (chain testChain) CurrentHeaderHash() util.Uint256 {
|
func (chain testChain) CurrentHeaderHash() util.Uint256 {
|
||||||
return util.Uint256{}
|
return util.Uint256{}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue