fix(ledger): new view ledger instance err

1. move the ledger db initialization part out of Ledger constrcutor
2. revise unit test and tester
This commit is contained in:
Alexader 2020-07-14 16:26:42 +08:00
parent 447f699bf9
commit 7f6da37901
13 changed files with 267 additions and 93 deletions

View File

@ -28,7 +28,7 @@ func (cbs *ChainBrokerService) SendTransaction(ctx context.Context, tx *pb.SendT
return &pb.TransactionHashMsg{TxHash: hash}, nil
}
func (cbs *ChainBrokerService) SendView(ctx context.Context, tx *pb.SendTransactionRequest) ([]byte, error) {
func (cbs *ChainBrokerService) SendView(ctx context.Context, tx *pb.SendTransactionRequest) (*pb.Response, error) {
if err := cbs.checkTransaction(tx); err != nil {
return nil, err
}
@ -38,7 +38,7 @@ func (cbs *ChainBrokerService) SendView(ctx context.Context, tx *pb.SendTransact
return nil, err
}
return result, nil
return &pb.Response{Data: result}, nil
}
func (cbs *ChainBrokerService) checkTransaction(tx *pb.SendTransactionRequest) error {

2
go.mod
View File

@ -23,7 +23,7 @@ require (
github.com/magiconair/properties v1.8.1
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20200526060151-b0efad4a2046
github.com/meshplus/bitxhub-kit v1.0.1-0.20200525060338-39d86f7542ae
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200707045101-18b88b80efb1
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200714081853-9d050b7250ad
github.com/mitchellh/go-homedir v1.1.0
github.com/multiformats/go-multiaddr v0.2.0
github.com/pkg/errors v0.9.1

2
go.sum
View File

@ -512,6 +512,8 @@ github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200514093243-7e8ae60d1c19 h1:D0
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200514093243-7e8ae60d1c19/go.mod h1:QK8aACbxtZEA3Hk1BOCirW0uxMWLsMrLDpWz9FweIKM=
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200707045101-18b88b80efb1 h1:g9VI4+6v/G5W9dvdclfrOfCk/ZxQOhrEKtOH+vHcHgs=
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200707045101-18b88b80efb1/go.mod h1:QK8aACbxtZEA3Hk1BOCirW0uxMWLsMrLDpWz9FweIKM=
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200714081853-9d050b7250ad h1:lZQQlcwrI4BGKVdA4O2VW93K4P7wL04o3ODoFUESOBo=
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200714081853-9d050b7250ad/go.mod h1:QK8aACbxtZEA3Hk1BOCirW0uxMWLsMrLDpWz9FweIKM=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/pkcs11 v1.0.3 h1:iMwmD7I5225wv84WxIG/bmxz9AXjWvTWIbM/TYHvWtw=

View File

@ -18,6 +18,7 @@ import (
"github.com/meshplus/bitxhub/pkg/order"
"github.com/meshplus/bitxhub/pkg/order/etcdraft"
"github.com/meshplus/bitxhub/pkg/peermgr"
"github.com/meshplus/bitxhub/pkg/storage/leveldb"
"github.com/sirupsen/logrus"
)
@ -99,9 +100,14 @@ func generateBitXHubWithoutOrder(rep *repo.Repo) (*BitXHub, error) {
return nil, fmt.Errorf("create blockchain storage: %w", err)
}
ldb, err := leveldb.New(repo.GetStoragePath(repoRoot, "ledger"))
if err != nil {
return nil, fmt.Errorf("create tm-leveldb: %w", err)
}
// 0. load ledger
accountCache := ledger.NewAccountCache()
rwLdg, err := ledger.New(repoRoot, bcStorage, accountCache, loggers.Logger(loggers.Executor), false)
rwLdg, err := ledger.New(bcStorage, ldb, accountCache, loggers.Logger(loggers.Executor), false)
if err != nil {
return nil, fmt.Errorf("create RW ledger: %w", err)
}
@ -114,7 +120,7 @@ func generateBitXHubWithoutOrder(rep *repo.Repo) (*BitXHub, error) {
}
// create read only ledger
viewLdg, err := ledger.New(repoRoot, bcStorage, accountCache, loggers.Logger(loggers.Executor), true)
viewLdg, err := ledger.New(bcStorage, ldb, accountCache, loggers.Logger(loggers.Executor), true)
if err != nil {
return nil, fmt.Errorf("create readonly ledger: %w", err)
}

View File

@ -171,22 +171,24 @@ func TestBlockExecutor_ExecuteBlock_Transfer(t *testing.T) {
blockchainStorage, err := leveldb.New(filepath.Join(repoRoot, "storage"))
require.Nil(t, err)
ldb, err := leveldb.New(filepath.Join(repoRoot, "ledger"))
require.Nil(t, err)
accountCache := ledger.NewAccountCache()
ledger, err := ledger.New(repoRoot, blockchainStorage, accountCache, log.NewWithModule("ledger"), false)
ldg, err := ledger.New(blockchainStorage, ldb, accountCache, log.NewWithModule("ledger"), false)
require.Nil(t, err)
_, from := loadAdminKey(t)
require.Nil(t, ledger.SetBalance(from, 100000000))
account, journal, err := ledger.FlushDirtyDataAndComputeJournal()
require.Nil(t, ldg.SetBalance(from, 100000000))
account, journal, err := ldg.FlushDirtyDataAndComputeJournal()
require.Nil(t, err)
err = ledger.Commit(1, account, journal)
err = ldg.Commit(1, account, journal)
require.Nil(t, err)
err = ledger.PersistExecutionResult(mockBlock(1, nil), nil, &pb.InterchainMeta{})
err = ldg.PersistExecutionResult(mockBlock(1, nil), nil, &pb.InterchainMeta{})
require.Nil(t, err)
executor, err := New(ledger, log.NewWithModule("executor"))
executor, err := New(ldg, log.NewWithModule("executor"))
require.Nil(t, err)
err = executor.Start()
require.Nil(t, err)
@ -204,7 +206,20 @@ func TestBlockExecutor_ExecuteBlock_Transfer(t *testing.T) {
block := <-ch
require.EqualValues(t, 2, block.Block.Height())
require.EqualValues(t, 99999997, ledger.GetBalance(from))
require.EqualValues(t, 99999997, ldg.GetBalance(from))
// test executor with readonly ledger
viewLedger, err := ledger.New(blockchainStorage, ldb, accountCache, log.NewWithModule("ledger"), true)
require.Nil(t, err)
exec, err := New(viewLedger, log.NewWithModule("executor"))
require.Nil(t, err)
tx := mockTransferTx(t)
receipts := exec.ApplyReadonlyTransactions([]*pb.Transaction{tx})
require.NotNil(t, receipts)
require.Equal(t, pb.Receipt_FAILED, receipts[0].Status)
require.Equal(t, ledger.ErrWriteToViewLedger.Error(), string(receipts[0].Ret))
}
func mockTransferTx(t *testing.T) *pb.Transaction {

View File

@ -2,6 +2,7 @@ package ledger
import (
"io/ioutil"
"path/filepath"
"testing"
"github.com/meshplus/bitxhub-kit/bytesutil"
@ -18,11 +19,13 @@ func TestAccount_GetState(t *testing.T) {
assert.Nil(t, err)
repoRoot, err := ioutil.TempDir("", "ledger_commit")
assert.Nil(t, err)
blockStorage, err := leveldb.New(repoRoot)
blockStorage, err := leveldb.New(filepath.Join(repoRoot, "storage"))
assert.Nil(t, err)
ldb, err := leveldb.New(filepath.Join(repoRoot, "ledger"))
assert.Nil(t, err)
accountCache := NewAccountCache()
ledger, err := New(repoRoot, blockStorage, accountCache, log.NewWithModule("ChainLedger"), false)
ledger, err := New(blockStorage, ldb, accountCache, log.NewWithModule("ChainLedger"), false)
assert.Nil(t, err)
h := hexutil.Encode(bytesutil.LeftPadBytes([]byte{11}, 20))

View File

@ -13,7 +13,7 @@ import (
// PutBlock put block into store
func (l *ChainLedger) PutBlock(height uint64, block *pb.Block) error {
if l.readOnly {
return writeToReadOnlyErr()
return ErrWriteToViewLedger
}
data, err := block.Marshal()
@ -123,7 +123,7 @@ func (l *ChainLedger) GetReceipt(hash types.Hash) (*pb.Receipt, error) {
// PersistExecutionResult persist the execution result
func (l *ChainLedger) PersistExecutionResult(block *pb.Block, receipts []*pb.Receipt, interchainMeta *pb.InterchainMeta) error {
if l.readOnly {
return writeToReadOnlyErr()
return ErrWriteToViewLedger
}
current := time.Now()
@ -180,7 +180,7 @@ func (l *ChainLedger) PersistExecutionResult(block *pb.Block, receipts []*pb.Rec
// UpdateChainMeta update the chain meta data
func (l *ChainLedger) UpdateChainMeta(meta *pb.ChainMeta) error {
if l.readOnly {
return writeToReadOnlyErr()
return ErrWriteToViewLedger
}
l.chainMutex.Lock()

View File

@ -26,7 +26,3 @@ func compositeKey(prefix string, value interface{}) []byte {
func composeStateKey(addr types.Address, key []byte) []byte {
return append(addr.Bytes(), key...)
}
func writeToReadOnlyErr() error {
return fmt.Errorf("have no access to write readonly ledger")
}

View File

@ -7,9 +7,7 @@ import (
"github.com/meshplus/bitxhub-kit/types"
"github.com/meshplus/bitxhub-model/pb"
"github.com/meshplus/bitxhub/internal/repo"
"github.com/meshplus/bitxhub/pkg/storage"
"github.com/meshplus/bitxhub/pkg/storage/leveldb"
"github.com/sirupsen/logrus"
)
@ -20,6 +18,7 @@ var (
ErrorRollbackWithoutJournal = fmt.Errorf("rollback to blockchain height without journal")
ErrorRollbackTooMuch = fmt.Errorf("rollback too much block")
ErrorRemoveJournalOutOfRange = fmt.Errorf("remove journal out of range")
ErrWriteToViewLedger = fmt.Errorf("have no access to write readonly ledger")
)
type ChainLedger struct {
@ -49,12 +48,7 @@ type BlockData struct {
}
// New create a new ledger instance
func New(repoRoot string, blockchainStore storage.Storage, accountCache *AccountCache, logger logrus.FieldLogger, readOnly bool) (*ChainLedger, error) {
ldb, err := leveldb.New(repo.GetStoragePath(repoRoot, "ledger"))
if err != nil {
return nil, fmt.Errorf("create tm-leveldb: %w", err)
}
func New(blockchainStore storage.Storage, ldb storage.Storage, accountCache *AccountCache, logger logrus.FieldLogger, readOnly bool) (*ChainLedger, error) {
chainMeta, err := loadChainMeta(blockchainStore)
if err != nil {
return nil, fmt.Errorf("load chain meta: %w", err)
@ -87,8 +81,10 @@ func New(repoRoot string, blockchainStore storage.Storage, accountCache *Account
height = chainMeta.Height
}
if err := ledger.Rollback(height); err != nil {
return nil, err
if !readOnly {
if err := ledger.Rollback(height); err != nil {
return nil, err
}
}
return ledger, nil
@ -97,7 +93,7 @@ func New(repoRoot string, blockchainStore storage.Storage, accountCache *Account
// PersistBlockData persists block data
func (l *ChainLedger) PersistBlockData(blockData *BlockData) error {
if l.readOnly {
return writeToReadOnlyErr()
return ErrWriteToViewLedger
}
current := time.Now()
@ -128,7 +124,7 @@ func (l *ChainLedger) PersistBlockData(blockData *BlockData) error {
// Rollback rollback ledger to history version
func (l *ChainLedger) Rollback(height uint64) error {
if l.readOnly {
return writeToReadOnlyErr()
return ErrWriteToViewLedger
}
if err := l.rollbackState(height); err != nil {
@ -145,7 +141,7 @@ func (l *ChainLedger) Rollback(height uint64) error {
// RemoveJournalsBeforeBlock removes ledger journals whose block number < height
func (l *ChainLedger) RemoveJournalsBeforeBlock(height uint64) error {
if l.readOnly {
return writeToReadOnlyErr()
return ErrWriteToViewLedger
}
l.journalMutex.Lock()
@ -174,7 +170,7 @@ func (l *ChainLedger) RemoveJournalsBeforeBlock(height uint64) error {
// AddEvent add ledger event
func (l *ChainLedger) AddEvent(event *pb.Event) error {
if l.readOnly {
return writeToReadOnlyErr()
return ErrWriteToViewLedger
}
hash := event.TxHash.Hex()

View File

@ -4,6 +4,7 @@ import (
"crypto/sha256"
"encoding/hex"
"io/ioutil"
"path/filepath"
"testing"
"github.com/meshplus/bitxhub-kit/bytesutil"
@ -19,25 +20,41 @@ import (
func TestLedger_Commit(t *testing.T) {
repoRoot, err := ioutil.TempDir("", "ledger_commit")
assert.Nil(t, err)
blockStorage, err := leveldb.New(repoRoot)
blockStorage, err := leveldb.New(filepath.Join(repoRoot, "storage"))
assert.Nil(t, err)
ldb, err := leveldb.New(filepath.Join(repoRoot, "ledger"))
assert.Nil(t, err)
ledger, err := New(repoRoot, blockStorage, NewAccountCache(), log.NewWithModule("executor"), false)
accountCache := NewAccountCache()
ledger, err := New(blockStorage, ldb, accountCache, log.NewWithModule("executor"), false)
assert.Nil(t, err)
// create readonly ledger
viewLedger, err := New(blockStorage, ldb, accountCache, log.NewWithModule("executor"), true)
assert.Nil(t, err)
// create an account
account := types.Bytes2Address(bytesutil.LeftPadBytes([]byte{100}, 20))
assert.Nil(t, ledger.SetState(account, []byte("a"), []byte("b")))
assert.Equal(t, ErrWriteToViewLedger, viewLedger.SetState(account, []byte("a"), []byte("b")))
_, _, err = viewLedger.FlushDirtyDataAndComputeJournal()
assert.Equal(t, ErrWriteToViewLedger, err)
accounts, journal, err := ledger.FlushDirtyDataAndComputeJournal()
assert.Nil(t, err)
assert.Equal(t, ErrWriteToViewLedger, viewLedger.PersistBlockData(genBlockData(1, accounts, journal)))
assert.Nil(t, ledger.PersistBlockData(genBlockData(1, accounts, journal)))
assert.Equal(t, uint64(1), ledger.Version())
assert.Equal(t, "0xa1a6d35708fa6cf804b6cf9479f3a55d9a87fbfb83c55a64685aeabdba6116b1", journal.ChangedHash.Hex())
_, _, err = viewLedger.FlushDirtyDataAndComputeJournal()
assert.Equal(t, ErrWriteToViewLedger, err)
accounts, journal, err = ledger.FlushDirtyDataAndComputeJournal()
assert.Nil(t, err)
assert.Equal(t, ErrWriteToViewLedger, viewLedger.PersistBlockData(genBlockData(2, accounts, journal)))
assert.Nil(t, ledger.PersistBlockData(genBlockData(2, accounts, journal)))
assert.Equal(t, uint64(2), ledger.Version())
assert.Equal(t, "0xf09f0198c06d549316d4ee7c497c9eaef9d24f5b1075e7bcef3d0a82dfa742cf", journal.ChangedHash.Hex())
@ -91,8 +108,10 @@ func TestLedger_Commit(t *testing.T) {
ledger.Close()
ldb, err = leveldb.New(filepath.Join(repoRoot, "ledger"))
assert.Nil(t, err)
// load ChainLedger from db
ldg, err := New(repoRoot, blockStorage, NewAccountCache(), log.NewWithModule("executor"), false)
ldg, err := New(blockStorage, ldb, NewAccountCache(), log.NewWithModule("executor"), false)
assert.Nil(t, err)
assert.Equal(t, uint64(5), ldg.maxJnlHeight)
assert.Equal(t, journal.ChangedHash, ldg.prevJnlHash)
@ -119,9 +138,12 @@ func TestLedger_Commit(t *testing.T) {
func TestChainLedger_Rollback(t *testing.T) {
repoRoot, err := ioutil.TempDir("", "ledger_rollback")
assert.Nil(t, err)
blockStorage, err := leveldb.New(repoRoot)
blockStorage, err := leveldb.New(filepath.Join(repoRoot, "storage"))
assert.Nil(t, err)
ledger, err := New(repoRoot, blockStorage, NewAccountCache(), log.NewWithModule("executor"), false)
ldb, err := leveldb.New(filepath.Join(repoRoot, "ledger"))
assert.Nil(t, err)
ledger, err := New(blockStorage, ldb, NewAccountCache(), log.NewWithModule("executor"), false)
assert.Nil(t, err)
// create an addr0
@ -222,7 +244,11 @@ func TestChainLedger_Rollback(t *testing.T) {
assert.Nil(t, account1.Code())
ledger.Close()
ledger, err = New(repoRoot, blockStorage, NewAccountCache(), log.NewWithModule("executor"), false)
ldb, err = leveldb.New(filepath.Join(repoRoot, "ledger"))
assert.Nil(t, err)
ledger, err = New(blockStorage, ldb, NewAccountCache(), log.NewWithModule("executor"), false)
assert.Nil(t, err)
assert.Equal(t, uint64(2), ledger.minJnlHeight)
assert.Equal(t, uint64(2), ledger.maxJnlHeight)
@ -234,9 +260,17 @@ func TestChainLedger_Rollback(t *testing.T) {
func TestChainLedger_RemoveJournalsBeforeBlock(t *testing.T) {
repoRoot, err := ioutil.TempDir("", "ledger_removeJournal")
assert.Nil(t, err)
blockStorage, err := leveldb.New(repoRoot)
blockStorage, err := leveldb.New(filepath.Join(repoRoot, "storage"))
assert.Nil(t, err)
ledger, err := New(repoRoot, blockStorage, NewAccountCache(), log.NewWithModule("executor"), false)
ldb, err := leveldb.New(filepath.Join(repoRoot, "ledger"))
assert.Nil(t, err)
accountCache := NewAccountCache()
ledger, err := New(blockStorage, ldb, accountCache, log.NewWithModule("executor"), false)
assert.Nil(t, err)
// create readonly ledger
viewLedger, err := New(blockStorage, ldb, accountCache, log.NewWithModule("executor"), true)
assert.Nil(t, err)
assert.Equal(t, uint64(0), ledger.minJnlHeight)
@ -245,6 +279,10 @@ func TestChainLedger_RemoveJournalsBeforeBlock(t *testing.T) {
accounts, journal, err := ledger.FlushDirtyDataAndComputeJournal()
assert.Nil(t, err)
require.Nil(t, ledger.PersistBlockData(genBlockData(1, accounts, journal)))
// test for writing to view ledger
_, _, err = viewLedger.FlushDirtyDataAndComputeJournal()
assert.Equal(t, ErrWriteToViewLedger, err)
accounts, journal, err = ledger.FlushDirtyDataAndComputeJournal()
assert.Nil(t, err)
require.Nil(t, ledger.PersistBlockData(genBlockData(2, accounts, journal)))
@ -260,6 +298,13 @@ func TestChainLedger_RemoveJournalsBeforeBlock(t *testing.T) {
minHeight, maxHeight := getJournalRange(ledger.ldb)
journal = getBlockJournal(maxHeight, ledger.ldb)
// test for view ledger
viewMinHeight, viewMaxHeight := getJournalRange(viewLedger.ldb)
viewJournal := getBlockJournal(maxHeight, viewLedger.ldb)
assert.Equal(t, uint64(1), viewMinHeight)
assert.Equal(t, uint64(4), viewMaxHeight)
assert.Equal(t, journal4.ChangedHash, viewJournal.ChangedHash)
// test for write and read ledger
assert.Equal(t, uint64(1), minHeight)
assert.Equal(t, uint64(4), maxHeight)
assert.Equal(t, journal4.ChangedHash, journal.ChangedHash)
@ -267,29 +312,42 @@ func TestChainLedger_RemoveJournalsBeforeBlock(t *testing.T) {
err = ledger.RemoveJournalsBeforeBlock(5)
assert.Equal(t, ErrorRemoveJournalOutOfRange, err)
// test for view ledger
assert.Equal(t, ErrWriteToViewLedger, viewLedger.RemoveJournalsBeforeBlock(2))
err = ledger.RemoveJournalsBeforeBlock(2)
assert.Nil(t, err)
assert.Equal(t, uint64(2), ledger.minJnlHeight)
assert.Equal(t, uint64(4), ledger.maxJnlHeight)
// test for view ledger
viewMinHeight, viewMaxHeight = getJournalRange(viewLedger.ldb)
viewJournal = getBlockJournal(maxHeight, viewLedger.ldb)
assert.Equal(t, uint64(2), viewMinHeight)
assert.Equal(t, uint64(4), viewMaxHeight)
assert.Equal(t, journal4.ChangedHash, viewJournal.ChangedHash)
minHeight, maxHeight = getJournalRange(ledger.ldb)
journal = getBlockJournal(maxHeight, ledger.ldb)
assert.Equal(t, uint64(2), minHeight)
assert.Equal(t, uint64(4), maxHeight)
assert.Equal(t, journal4.ChangedHash, journal.ChangedHash)
assert.Equal(t, ErrWriteToViewLedger, viewLedger.RemoveJournalsBeforeBlock(2))
err = ledger.RemoveJournalsBeforeBlock(2)
assert.Nil(t, err)
assert.Equal(t, uint64(2), ledger.minJnlHeight)
assert.Equal(t, uint64(4), ledger.maxJnlHeight)
assert.Equal(t, ErrWriteToViewLedger, viewLedger.RemoveJournalsBeforeBlock(1))
err = ledger.RemoveJournalsBeforeBlock(1)
assert.Nil(t, err)
assert.Equal(t, uint64(2), ledger.minJnlHeight)
assert.Equal(t, uint64(4), ledger.maxJnlHeight)
assert.Equal(t, ErrWriteToViewLedger, viewLedger.RemoveJournalsBeforeBlock(4))
err = ledger.RemoveJournalsBeforeBlock(4)
assert.Nil(t, err)
@ -304,19 +362,36 @@ func TestChainLedger_RemoveJournalsBeforeBlock(t *testing.T) {
assert.Equal(t, journal4.ChangedHash, journal.ChangedHash)
ledger.Close()
ledger, err = New(repoRoot, blockStorage, NewAccountCache(), log.NewWithModule("executor"), false)
ldb, err = leveldb.New(filepath.Join(repoRoot, "ledger"))
assert.Nil(t, err)
accountCache = NewAccountCache()
ledger, err = New(blockStorage, ldb, accountCache, log.NewWithModule("executor"), false)
assert.Nil(t, err)
viewLedger, err = New(blockStorage, ldb, accountCache, log.NewWithModule("executor"), true)
assert.Nil(t, err)
assert.Equal(t, uint64(4), ledger.minJnlHeight)
assert.Equal(t, uint64(4), ledger.maxJnlHeight)
assert.Equal(t, journal4.ChangedHash, ledger.prevJnlHash)
assert.Equal(t, uint64(4), viewLedger.minJnlHeight)
assert.Equal(t, uint64(4), viewLedger.maxJnlHeight)
assert.Equal(t, journal4.ChangedHash, viewLedger.prevJnlHash)
}
func TestChainLedger_QueryByPrefix(t *testing.T) {
repoRoot, err := ioutil.TempDir("", "ledger_queryByPrefix")
assert.Nil(t, err)
blockStorage, err := leveldb.New(repoRoot)
blockStorage, err := leveldb.New(filepath.Join(repoRoot, "storage"))
assert.Nil(t, err)
ledger, err := New(repoRoot, blockStorage, NewAccountCache(), log.NewWithModule("executor"), false)
ldb, err := leveldb.New(filepath.Join(repoRoot, "ledger"))
assert.Nil(t, err)
accountCache := NewAccountCache()
ledger, err := New(blockStorage, ldb, accountCache, log.NewWithModule("executor"), false)
assert.Nil(t, err)
viewLedger, err := New(blockStorage, ldb, accountCache, log.NewWithModule("executor"), true)
assert.Nil(t, err)
addr := types.Bytes2Address(bytesutil.LeftPadBytes([]byte{1}, 20))
@ -325,21 +400,31 @@ func TestChainLedger_QueryByPrefix(t *testing.T) {
key2 := []byte{100, 102}
key3 := []byte{10, 102}
require.Equal(t, ErrWriteToViewLedger, viewLedger.SetState(addr, key0, []byte("0")))
require.Equal(t, ErrWriteToViewLedger, viewLedger.SetState(addr, key0, []byte("1")))
require.Equal(t, ErrWriteToViewLedger, viewLedger.SetState(addr, key0, []byte("2")))
require.Equal(t, ErrWriteToViewLedger, viewLedger.SetState(addr, key0, []byte("3")))
require.Nil(t, ledger.SetState(addr, key0, []byte("0")))
require.Nil(t, ledger.SetState(addr, key1, []byte("1")))
require.Nil(t, ledger.SetState(addr, key2, []byte("2")))
require.Nil(t, ledger.SetState(addr, key3, []byte("2")))
_, _, err = viewLedger.FlushDirtyDataAndComputeJournal()
require.Equal(t, ErrWriteToViewLedger, err)
accounts, journal, err := ledger.FlushDirtyDataAndComputeJournal()
assert.Nil(t, err)
ok, vals := ledger.QueryByPrefix(addr, string([]byte{100}))
ok, vals := viewLedger.QueryByPrefix(addr, string([]byte{100}))
assert.True(t, ok)
ok, vals = ledger.QueryByPrefix(addr, string([]byte{100}))
assert.True(t, ok)
assert.Equal(t, 3, len(vals))
assert.Equal(t, []byte("0"), vals[0])
assert.Equal(t, []byte("1"), vals[1])
assert.Equal(t, []byte("2"), vals[2])
assert.Equal(t, ErrWriteToViewLedger, viewLedger.Commit(1, accounts, journal))
err = ledger.Commit(1, accounts, journal)
assert.Nil(t, err)
@ -355,9 +440,16 @@ func TestChainLedger_QueryByPrefix(t *testing.T) {
func TestChainLedger_GetAccount(t *testing.T) {
repoRoot, err := ioutil.TempDir("", "ledger_getAccount")
assert.Nil(t, err)
blockStorage, err := leveldb.New(repoRoot)
blockStorage, err := leveldb.New(filepath.Join(repoRoot, "storage"))
assert.Nil(t, err)
ledger, err := New(repoRoot, blockStorage, NewAccountCache(), log.NewWithModule("executor"), false)
ldb, err := leveldb.New(filepath.Join(repoRoot, "ledger"))
assert.Nil(t, err)
accountCache := NewAccountCache()
ledger, err := New(blockStorage, ldb, accountCache, log.NewWithModule("executor"), false)
assert.Nil(t, err)
viewLedger, err := New(blockStorage, ldb, accountCache, log.NewWithModule("executor"), true)
assert.Nil(t, err)
addr := types.Bytes2Address(bytesutil.LeftPadBytes([]byte{1}, 20))
@ -373,39 +465,73 @@ func TestChainLedger_GetAccount(t *testing.T) {
account.SetState(key0, key1)
account.SetState(key1, key0)
_, _, err = viewLedger.FlushDirtyDataAndComputeJournal()
assert.Equal(t, ErrWriteToViewLedger, err)
accounts, journal, err := ledger.FlushDirtyDataAndComputeJournal()
assert.Nil(t, err)
assert.Equal(t, ErrWriteToViewLedger, viewLedger.Commit(1, accounts, journal))
err = ledger.Commit(1, accounts, journal)
assert.Nil(t, err)
viewAccount1 := viewLedger.GetAccount(addr)
account1 := ledger.GetAccount(addr)
// test view ledger
assert.Equal(t, account1.GetBalance(), viewLedger.GetBalance(addr))
assert.Equal(t, account1.GetBalance(), viewAccount1.GetBalance())
assert.Equal(t, account1.GetNonce(), viewAccount1.GetNonce())
assert.Equal(t, account1.CodeHash(), viewAccount1.CodeHash())
assert.Equal(t, account1.Code(), viewAccount1.Code())
ok0, val0 := viewAccount1.GetState(key0)
ok1, val1 := viewAccount1.GetState(key1)
assert.Equal(t, ok0, ok1)
assert.Equal(t, val0, key1)
assert.Equal(t, val1, key0)
// test rw ledger
assert.Equal(t, account.GetBalance(), ledger.GetBalance(addr))
assert.Equal(t, account.GetBalance(), account1.GetBalance())
assert.Equal(t, account.GetNonce(), account1.GetNonce())
assert.Equal(t, account.CodeHash(), account1.CodeHash())
assert.Equal(t, account.Code(), account1.Code())
ok0, val0 := account.GetState(key0)
ok1, val1 := account.GetState(key1)
ok0, val0 = account.GetState(key0)
ok1, val1 = account.GetState(key1)
assert.Equal(t, ok0, ok1)
assert.Equal(t, val0, key1)
assert.Equal(t, val1, key0)
key2 := []byte{100, 102}
val2 := []byte{111}
require.Equal(t, ErrWriteToViewLedger, viewLedger.SetState(addr, key0, val0))
require.Equal(t, ErrWriteToViewLedger, viewLedger.SetState(addr, key2, val2))
require.Equal(t, ErrWriteToViewLedger, viewLedger.SetState(addr, key0, val1))
require.Nil(t, ledger.SetState(addr, key0, val0))
require.Nil(t, ledger.SetState(addr, key2, val2))
require.Nil(t, ledger.SetState(addr, key0, val1))
_, _, err = viewLedger.FlushDirtyDataAndComputeJournal()
assert.Equal(t, ErrWriteToViewLedger, err)
assert.Equal(t, ErrWriteToViewLedger, viewLedger.Commit(2, accounts, journal))
accounts, journal, err = ledger.FlushDirtyDataAndComputeJournal()
assert.Nil(t, err)
err = ledger.Commit(2, accounts, journal)
assert.Nil(t, err)
assert.Equal(t, ErrWriteToViewLedger, viewLedger.SetState(addr, key0, val0))
assert.Equal(t, ErrWriteToViewLedger, viewLedger.SetState(addr, key0, val1))
assert.Equal(t, ErrWriteToViewLedger, viewLedger.SetState(addr, key2, nil))
require.Nil(t, ledger.SetState(addr, key0, val0))
require.Nil(t, ledger.SetState(addr, key0, val1))
require.Nil(t, ledger.SetState(addr, key2, nil))
_, _, err = viewLedger.FlushDirtyDataAndComputeJournal()
assert.Equal(t, ErrWriteToViewLedger, err)
accounts, journal, err = ledger.FlushDirtyDataAndComputeJournal()
assert.Nil(t, err)
assert.Equal(t, ErrWriteToViewLedger, viewLedger.Commit(3, accounts, journal))
err = ledger.Commit(3, accounts, journal)
assert.Nil(t, err)
@ -421,9 +547,12 @@ func TestChainLedger_GetAccount(t *testing.T) {
func TestChainLedger_GetCode(t *testing.T) {
repoRoot, err := ioutil.TempDir("", "ledger_getCode")
assert.Nil(t, err)
blockStorage, err := leveldb.New(repoRoot)
blockStorage, err := leveldb.New(filepath.Join(repoRoot, "storage"))
assert.Nil(t, err)
ledger, err := New(repoRoot, blockStorage, NewAccountCache(), log.NewWithModule("executor"), false)
ldb, err := leveldb.New(filepath.Join(repoRoot, "ledger"))
assert.Nil(t, err)
ledger, err := New(blockStorage, ldb, NewAccountCache(), log.NewWithModule("executor"), false)
assert.Nil(t, err)
addr := types.Bytes2Address(bytesutil.LeftPadBytes([]byte{1}, 20))
@ -457,9 +586,12 @@ func TestChainLedger_GetCode(t *testing.T) {
func TestChainLedger_AddAccountsToCache(t *testing.T) {
repoRoot, err := ioutil.TempDir("", "ledger_addAccountToCache")
assert.Nil(t, err)
blockStorage, err := leveldb.New(repoRoot)
blockStorage, err := leveldb.New(filepath.Join(repoRoot, "storage"))
assert.Nil(t, err)
ledger, err := New(repoRoot, blockStorage, NewAccountCache(), log.NewWithModule("executor"), false)
ldb, err := leveldb.New(filepath.Join(repoRoot, "ledger"))
assert.Nil(t, err)
ledger, err := New(blockStorage, ldb, NewAccountCache(), log.NewWithModule("executor"), false)
assert.Nil(t, err)
addr := types.Bytes2Address(bytesutil.LeftPadBytes([]byte{1}, 20))
@ -522,9 +654,12 @@ func TestChainLedger_AddAccountsToCache(t *testing.T) {
func TestChainLedger_GetInterchainMeta(t *testing.T) {
repoRoot, err := ioutil.TempDir("", "ledger_GetInterchainMeta")
require.Nil(t, err)
blockStorage, err := leveldb.New(repoRoot)
require.Nil(t, err)
ledger, err := New(repoRoot, blockStorage, NewAccountCache(), log.NewWithModule("executor"), false)
blockStorage, err := leveldb.New(filepath.Join(repoRoot, "storage"))
assert.Nil(t, err)
ldb, err := leveldb.New(filepath.Join(repoRoot, "ledger"))
assert.Nil(t, err)
ledger, err := New(blockStorage, ldb, NewAccountCache(), log.NewWithModule("executor"), false)
require.Nil(t, err)
// create an account

View File

@ -54,7 +54,7 @@ func (l *ChainLedger) GetBalance(addr types.Address) uint64 {
// SetBalance set account balance
func (l *ChainLedger) SetBalance(addr types.Address, value uint64) error {
if l.readOnly {
return writeToReadOnlyErr()
return ErrWriteToViewLedger
}
account := l.GetOrCreateAccount(addr)
@ -71,7 +71,7 @@ func (l *ChainLedger) GetState(addr types.Address, key []byte) (bool, []byte) {
// SetState set account state value using account Address and key
func (l *ChainLedger) SetState(addr types.Address, key []byte, v []byte) error {
if l.readOnly {
return writeToReadOnlyErr()
return ErrWriteToViewLedger
}
account := l.GetOrCreateAccount(addr)
@ -82,7 +82,7 @@ func (l *ChainLedger) SetState(addr types.Address, key []byte, v []byte) error {
// SetCode set contract code
func (l *ChainLedger) SetCode(addr types.Address, code []byte) error {
if l.readOnly {
return writeToReadOnlyErr()
return ErrWriteToViewLedger
}
account := l.GetOrCreateAccount(addr)
@ -105,7 +105,7 @@ func (l *ChainLedger) GetNonce(addr types.Address) uint64 {
// SetNonce set account nonce
func (l *ChainLedger) SetNonce(addr types.Address, nonce uint64) error {
if l.readOnly {
return writeToReadOnlyErr()
return ErrWriteToViewLedger
}
account := l.GetOrCreateAccount(addr)
@ -121,7 +121,7 @@ func (l *ChainLedger) QueryByPrefix(addr types.Address, prefix string) (bool, []
func (l *ChainLedger) Clear() error {
if l.readOnly {
return writeToReadOnlyErr()
return ErrWriteToViewLedger
}
l.events = make(map[string][]*pb.Event, 10)
@ -132,7 +132,7 @@ func (l *ChainLedger) Clear() error {
// FlushDirtyDataAndComputeJournal gets dirty accounts and computes block journal
func (l *ChainLedger) FlushDirtyDataAndComputeJournal() (map[string]*Account, *BlockJournal, error) {
if l.readOnly {
return nil, nil, writeToReadOnlyErr()
return nil, nil, ErrWriteToViewLedger
}
dirtyAccounts := make(map[string]*Account)
@ -175,7 +175,7 @@ func (l *ChainLedger) FlushDirtyDataAndComputeJournal() (map[string]*Account, *B
// Commit commit the state
func (l *ChainLedger) Commit(height uint64, accounts map[string]*Account, blockJournal *BlockJournal) error {
if l.readOnly {
return writeToReadOnlyErr()
return ErrWriteToViewLedger
}
ldbBatch := l.ldb.NewBatch()

View File

@ -54,7 +54,11 @@ func initCreateContext(t *testing.T, name string) *vm.Context {
store, err := leveldb.New(filepath.Join(dir, "wasm"))
assert.Nil(t, err)
ldg, err := ledger.New(dir, store, ledger.NewAccountCache(), log.NewWithModule("executor"), false)
ldb, err := leveldb.New(filepath.Join(dir, "ledger"))
assert.Nil(t, err)
ldg, err := ledger.New(store, ldb, ledger.NewAccountCache(), log.NewWithModule("executor"), false)
assert.Nil(t, err)
return &vm.Context{
@ -81,7 +85,10 @@ func initValidationContext(t *testing.T, name string) *vm.Context {
store, err := leveldb.New(filepath.Join(dir, "validation"))
assert.Nil(t, err)
ldg, err := ledger.New(dir, store, ledger.NewAccountCache(), log.NewWithModule("executor"), false)
ldb, err := leveldb.New(filepath.Join(dir, "ledger"))
assert.Nil(t, err)
ldg, err := ledger.New(store, ldb, ledger.NewAccountCache(), log.NewWithModule("executor"), false)
require.Nil(t, err)
return &vm.Context{
@ -108,7 +115,10 @@ func initFabricContext(t *testing.T, name string) *vm.Context {
store, err := leveldb.New(filepath.Join(dir, "validation_farbic"))
assert.Nil(t, err)
ldg, err := ledger.New(dir, store, ledger.NewAccountCache(), log.NewWithModule("executor"), false)
ldb, err := leveldb.New(filepath.Join(dir, "ledger"))
assert.Nil(t, err)
ldg, err := ledger.New(store, ldb, ledger.NewAccountCache(), log.NewWithModule("executor"), false)
require.Nil(t, err)
return &vm.Context{
@ -234,7 +244,10 @@ func BenchmarkRunFabValidation(b *testing.B) {
store, err := leveldb.New(filepath.Join(dir, "111"))
assert.Nil(b, err)
ldg, err := ledger.New(dir, store, ledger.NewAccountCache(), log.NewWithModule("executor"), false)
ldb, err := leveldb.New(filepath.Join(dir, "ledger"))
assert.Nil(b, err)
ldg, err := ledger.New(store, ldb, ledger.NewAccountCache(), log.NewWithModule("executor"), false)
require.Nil(b, err)
ctx := &vm.Context{
Caller: caller,

View File

@ -1,10 +1,11 @@
package tester
import (
"math/rand"
"testing"
"time"
"github.com/Rican7/retry"
"github.com/Rican7/retry/strategy"
"github.com/meshplus/bitxhub-kit/crypto"
"github.com/meshplus/bitxhub-kit/crypto/asym"
"github.com/meshplus/bitxhub-kit/types"
@ -14,6 +15,10 @@ import (
"github.com/stretchr/testify/suite"
)
const (
value = "value"
)
type API struct {
suite.Suite
api api.CoreAPI
@ -32,36 +37,39 @@ func (suite *API) SetupSuite() {
suite.from = from
}
func (suite *API) TestSendTransaction() {
pl := &pb.InvokePayload{
Method: "Set",
Args: []*pb.Arg{
pb.String("key"),
pb.String("value"),
},
func (suite *API) TestSend() {
hash := testSendTransaction(suite)
if err := retry.Retry(func(attempt uint) error {
receipt, err := suite.api.Broker().GetReceipt(hash)
if err != nil {
return err
}
if receipt.IsSuccess() {
return nil
}
return nil
}, strategy.Wait(2*time.Second)); err != nil {
}
data, err := pl.Marshal()
suite.Assert().Nil(err)
testSendView(suite)
}
tx := &pb.Transaction{
From: suite.from,
To: constant.StoreContractAddr.Address(),
Timestamp: time.Now().UnixNano(),
Data: &pb.TransactionData{
Type: pb.TransactionData_INVOKE,
VmType: pb.TransactionData_BVM,
Payload: data,
},
Nonce: rand.Int63(),
}
err = tx.Sign(suite.privKey)
func testSendTransaction(suite *API) types.Hash {
tx, err := genContractTransaction(pb.TransactionData_BVM, suite.privKey,
constant.StoreContractAddr.Address(), "Set", pb.String("key"), pb.String(value))
suite.Nil(err)
tx.TransactionHash = tx.Hash()
suite.Nil(suite.api.Broker().HandleTransaction(tx))
return tx.TransactionHash
}
err = suite.api.Broker().HandleTransaction(tx)
func testSendView(suite *API) {
tx, err := genContractTransaction(pb.TransactionData_BVM, suite.privKey,
constant.StoreContractAddr.Address(), "Get", pb.String("key"))
result, err := suite.api.Broker().HandleView(tx)
suite.Nil(err)
suite.Equal(value, string(result))
}
func TestAPI(t *testing.T) {