Commit 7d84bc46 authored by kingwang's avatar kingwang Committed by 33cn

update 0308

parent ff84df1a
...@@ -435,7 +435,7 @@ func genPrefixEdge(prefix []byte) (r []byte) { ...@@ -435,7 +435,7 @@ func genPrefixEdge(prefix []byte) (r []byte) {
return r return r
} }
// Mint gitt铸币 // Mint 铸币
func (acc *DB) Mint(addr string, amount int64) (*types.Receipt, error) { func (acc *DB) Mint(addr string, amount int64) (*types.Receipt, error) {
if !types.CheckAmount(amount) { if !types.CheckAmount(amount) {
return nil, types.ErrAmount return nil, types.ErrAmount
......
...@@ -5,9 +5,6 @@ ...@@ -5,9 +5,6 @@
package blockchain package blockchain
import ( import (
"bytes"
"github.com/33cn/chain33/common/merkle"
"github.com/33cn/chain33/queue" "github.com/33cn/chain33/queue"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
"github.com/33cn/chain33/util" "github.com/33cn/chain33/util"
...@@ -15,127 +12,5 @@ import ( ...@@ -15,127 +12,5 @@ import (
//执行区块将变成一个私有的函数 //执行区块将变成一个私有的函数
func execBlock(client queue.Client, prevStateRoot []byte, block *types.Block, errReturn bool, sync bool) (*types.BlockDetail, []*types.Transaction, error) { func execBlock(client queue.Client, prevStateRoot []byte, block *types.Block, errReturn bool, sync bool) (*types.BlockDetail, []*types.Transaction, error) {
//发送执行交易给execs模块 return util.ExecBlock(client, prevStateRoot, block, errReturn, sync, true)
//通过consensus module 再次检查
chainlog.Debug("ExecBlock", "height------->", block.Height, "ntx", len(block.Txs))
beg := types.Now()
defer func() {
chainlog.Info("ExecBlock", "height", block.Height, "ntx", len(block.Txs), "writebatchsync", sync, "cost", types.Since(beg))
}()
if errReturn && block.Height > 0 && !block.CheckSign() {
//block的来源不是自己的mempool,而是别人的区块
return nil, nil, types.ErrSign
}
//tx交易去重处理, 这个地方要查询数据库,需要一个更快的办法
cacheTxs := types.TxsToCache(block.Txs)
oldtxscount := len(cacheTxs)
var err error
cacheTxs, err = util.CheckTxDup(client, cacheTxs, block.Height)
if err != nil {
return nil, nil, err
}
newtxscount := len(cacheTxs)
if oldtxscount != newtxscount && errReturn {
return nil, nil, types.ErrTxDup
}
chainlog.Debug("ExecBlock", "prevtx", oldtxscount, "newtx", newtxscount)
block.TxHash = merkle.CalcMerkleRootCache(cacheTxs)
block.Txs = types.CacheToTxs(cacheTxs)
//println("1")
receipts, err := util.ExecTx(client, prevStateRoot, block)
if err != nil {
return nil, nil, err
}
var maplist = make(map[string]*types.KeyValue)
var kvset []*types.KeyValue
var deltxlist = make(map[int]bool)
var rdata []*types.ReceiptData //save to db receipt log
for i := 0; i < len(receipts.Receipts); i++ {
receipt := receipts.Receipts[i]
if receipt.Ty == types.ExecErr {
chainlog.Error("exec tx err", "err", receipt)
if errReturn { //认为这个是一个错误的区块
return nil, nil, types.ErrBlockExec
}
deltxlist[i] = true
continue
}
rdata = append(rdata, &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs})
//处理KV
kvs := receipt.KV
for _, kv := range kvs {
if item, ok := maplist[string(kv.Key)]; ok {
item.Value = kv.Value //更新item 的value
} else {
maplist[string(kv.Key)] = kv
kvset = append(kvset, kv)
}
}
}
//check TxHash
calcHash := merkle.CalcMerkleRoot(block.Txs)
if errReturn && !bytes.Equal(calcHash, block.TxHash) {
return nil, nil, types.ErrCheckTxHash
}
block.TxHash = calcHash
//删除无效的交易
var deltx []*types.Transaction
if len(deltxlist) > 0 {
var newtx []*types.Transaction
for i := 0; i < len(block.Txs); i++ {
if deltxlist[i] {
deltx = append(deltx, block.Txs[i])
} else {
newtx = append(newtx, block.Txs[i])
}
}
block.Txs = newtx
block.TxHash = merkle.CalcMerkleRoot(block.Txs)
}
var detail types.BlockDetail
calcHash, err = util.ExecKVMemSet(client, prevStateRoot, block.Height, kvset, sync)
if err != nil {
return nil, nil, err
}
//println("2")
if errReturn && !bytes.Equal(block.StateHash, calcHash) {
err = util.ExecKVSetRollback(client, calcHash)
if err != nil {
chainlog.Error("execBlock-->ExecKVSetRollback", "err", err)
}
if len(rdata) > 0 {
for i, rd := range rdata {
rd.OutputReceiptDetails(block.Txs[i].Execer, chainlog)
}
}
return nil, nil, types.ErrCheckStateHash
}
block.StateHash = calcHash
detail.Block = block
detail.Receipts = rdata
if detail.Block.Height > 0 {
err := util.CheckBlock(client, &detail)
if err != nil {
chainlog.Debug("CheckBlock-->", "err=", err)
return nil, deltx, err
}
}
//println("3")
//save to db
// 写数据库失败时需要及时返回错误,防止错误数据被写入localdb中CHAIN33-567
err = util.ExecKVSetCommit(client, block.StateHash)
if err != nil {
return nil, nil, err
}
detail.KV = kvset
detail.PrevStatusHash = prevStateRoot
//get receipts
//save kvset and get state hash
//ulog.Debug("blockdetail-->", "detail=", detail)
//println("4")
return &detail, deltx, nil
} }
...@@ -226,6 +226,10 @@ func (chain *BlockChain) ProcGetBlockDetailsMsg(requestblock *types.ReqBlocks) ( ...@@ -226,6 +226,10 @@ func (chain *BlockChain) ProcGetBlockDetailsMsg(requestblock *types.ReqBlocks) (
//ProcAddBlockMsg 处理从peer对端同步过来的block消息 //ProcAddBlockMsg 处理从peer对端同步过来的block消息
func (chain *BlockChain) ProcAddBlockMsg(broadcast bool, blockdetail *types.BlockDetail, pid string) (*types.BlockDetail, error) { func (chain *BlockChain) ProcAddBlockMsg(broadcast bool, blockdetail *types.BlockDetail, pid string) (*types.BlockDetail, error) {
beg := types.Now()
defer func() {
chainlog.Info("ProcAddBlockMsg", "cost", types.Since(beg))
}()
block := blockdetail.Block block := blockdetail.Block
if block == nil { if block == nil {
chainlog.Error("ProcAddBlockMsg input block is null") chainlog.Error("ProcAddBlockMsg input block is null")
......
...@@ -25,7 +25,7 @@ func TestReindex(t *testing.T) { ...@@ -25,7 +25,7 @@ func TestReindex(t *testing.T) {
chain := mock33.GetBlockChain() chain := mock33.GetBlockChain()
db := chain.GetDB() db := chain.GetDB()
kvs := getAllKeys(db) kvs := getAllKeys(db)
assert.Equal(t, len(kvs), 20) assert.Equal(t, len(kvs), 22)
defer mock33.Close() defer mock33.Close()
txs := util.GenCoinsTxs(mock33.GetGenesisKey(), 10) txs := util.GenCoinsTxs(mock33.GetGenesisKey(), 10)
for i := 0; i < len(txs); i++ { for i := 0; i < len(txs); i++ {
......
...@@ -97,11 +97,31 @@ func pow2(d int) (p int) { ...@@ -97,11 +97,31 @@ func pow2(d int) (p int) {
return p return p
} }
func calcLevel(n int) int {
if n == 1 {
return 1
}
level := 0
for n > 1 {
if n&1 != 0 {
n++
}
n = n / 2
level++
}
return level
}
func getMerkleRootPad(hashes [][]byte, step int) []byte { func getMerkleRootPad(hashes [][]byte, step int) []byte {
level1 := log2(len(hashes)) level1 := calcLevel(len(hashes))
level2 := log2(step) level2 := log2(step)
root := getMerkleRoot(hashes) var root []byte
cache := make([]byte, 64) cache := make([]byte, 64)
if len(hashes) == 1 {
root = GetHashFromTwoHash(cache, hashes[0], hashes[0])
} else {
root = getMerkleRoot(hashes)
}
for i := 0; i < level2-level1; i++ { for i := 0; i < level2-level1; i++ {
root = GetHashFromTwoHash(cache, root, root) root = GetHashFromTwoHash(cache, root, root)
} }
......
...@@ -331,9 +331,17 @@ func BenchmarkGetMerkelRoot2(b *testing.B) { ...@@ -331,9 +331,17 @@ func BenchmarkGetMerkelRoot2(b *testing.B) {
} }
} }
var testlen = 14
func TestGetMerkelRoot1(t *testing.T) { func TestGetMerkelRoot1(t *testing.T) {
for i := 0; i < 2000; i++ {
ok := testGetMerkelRoot1(t, i)
if !ok {
t.Error("calc merkel root error", i)
return
}
}
}
func testGetMerkelRoot1(t *testing.T, testlen int) bool {
var hashlist [][]byte var hashlist [][]byte
for i := 0; i < testlen; i++ { for i := 0; i < testlen; i++ {
key := sha256.Sum256([]byte(fmt.Sprint(i))) key := sha256.Sum256([]byte(fmt.Sprint(i)))
...@@ -347,7 +355,10 @@ func TestGetMerkelRoot1(t *testing.T) { ...@@ -347,7 +355,10 @@ func TestGetMerkelRoot1(t *testing.T) {
hashlist = append(hashlist, key[:]) hashlist = append(hashlist, key[:])
} }
hash2 := getMerkleRoot(hashlist) hash2 := getMerkleRoot(hashlist)
assert.Equal(t, hash1, hash2) if !bytes.Equal(hash1, hash2) {
println("failed1")
return false
}
hashlist = nil hashlist = nil
for i := 0; i < testlen; i++ { for i := 0; i < testlen; i++ {
...@@ -355,7 +366,11 @@ func TestGetMerkelRoot1(t *testing.T) { ...@@ -355,7 +366,11 @@ func TestGetMerkelRoot1(t *testing.T) {
hashlist = append(hashlist, key[:]) hashlist = append(hashlist, key[:])
} }
hash3, _, _ := Computation(hashlist, 1, 0) hash3, _, _ := Computation(hashlist, 1, 0)
assert.Equal(t, hash1, hash3) if !bytes.Equal(hash1, hash3) {
println("failed2")
return false
}
return true
} }
func TestLog2(t *testing.T) { func TestLog2(t *testing.T) {
......
...@@ -188,7 +188,7 @@ func TestExecBlock2(t *testing.T) { ...@@ -188,7 +188,7 @@ func TestExecBlock2(t *testing.T) {
txs := util.GenCoinsTxs(genkey, 2) txs := util.GenCoinsTxs(genkey, 2)
block2 := util.CreateNewBlock(block, txs) block2 := util.CreateNewBlock(block, txs)
detail, _, err := util.ExecBlock(mock33.GetClient(), block.StateHash, block2, false, true) detail, _, err := util.ExecBlock(mock33.GetClient(), block.StateHash, block2, false, true, false)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
...@@ -205,7 +205,7 @@ func TestExecBlock2(t *testing.T) { ...@@ -205,7 +205,7 @@ func TestExecBlock2(t *testing.T) {
go func() { go func() {
txs := util.GenCoinsTxs(genkey, 2) txs := util.GenCoinsTxs(genkey, 2)
block3 := util.CreateNewBlock(block2, txs) block3 := util.CreateNewBlock(block2, txs)
detail, _, err := util.ExecBlock(mock33.GetClient(), block2.StateHash, block3, false, true) detail, _, err := util.ExecBlock(mock33.GetClient(), block2.StateHash, block3, false, true, false)
assert.Nil(t, err) assert.Nil(t, err)
for _, Receipt := range detail.Receipts { for _, Receipt := range detail.Receipts {
if Receipt.GetTy() != 2 { if Receipt.GetTy() != 2 {
...@@ -234,7 +234,7 @@ func TestSameTx(t *testing.T) { ...@@ -234,7 +234,7 @@ func TestSameTx(t *testing.T) {
newblock.Txs = append(newblock.Txs, newblock.Txs[2]) newblock.Txs = append(newblock.Txs, newblock.Txs[2])
newblock.TxHash = merkle.CalcMerkleRoot(newblock.Txs) newblock.TxHash = merkle.CalcMerkleRoot(newblock.Txs)
assert.Equal(t, hash1, newblock.TxHash) assert.Equal(t, hash1, newblock.TxHash)
_, _, err := util.ExecBlock(mock33.GetClient(), nil, newblock, true, true) _, _, err := util.ExecBlock(mock33.GetClient(), nil, newblock, true, true, false)
assert.Equal(t, types.ErrTxDup, err) assert.Equal(t, types.ErrTxDup, err)
//情况2 //情况2
...@@ -244,15 +244,17 @@ func TestSameTx(t *testing.T) { ...@@ -244,15 +244,17 @@ func TestSameTx(t *testing.T) {
newblock.Txs = append(newblock.Txs, newblock.Txs[4:]...) newblock.Txs = append(newblock.Txs, newblock.Txs[4:]...)
newblock.TxHash = merkle.CalcMerkleRoot(newblock.Txs) newblock.TxHash = merkle.CalcMerkleRoot(newblock.Txs)
assert.Equal(t, hash1, newblock.TxHash) assert.Equal(t, hash1, newblock.TxHash)
_, _, err = util.ExecBlock(mock33.GetClient(), nil, newblock, true, true) _, _, err = util.ExecBlock(mock33.GetClient(), nil, newblock, true, true, false)
assert.Equal(t, types.ErrTxDup, err) assert.Equal(t, types.ErrTxDup, err)
} }
func TestExecBlock(t *testing.T) { func TestExecBlock(t *testing.T) {
mock33 := newMockNode() mock33 := newMockNode()
defer mock33.Close() defer mock33.Close()
block := util.CreateCoinsBlock(mock33.GetGenesisKey(), 1) mock33.WaitHeight(0)
util.ExecBlock(mock33.GetClient(), nil, block, false, true) block0 := mock33.GetBlock(0)
block := util.CreateCoinsBlock(mock33.GetGenesisKey(), 10)
util.ExecBlock(mock33.GetClient(), block0.StateHash, block, false, true, false)
} }
//区块执行性能更好的一个测试 //区块执行性能更好的一个测试
...@@ -274,7 +276,7 @@ func BenchmarkExecBlock(b *testing.B) { ...@@ -274,7 +276,7 @@ func BenchmarkExecBlock(b *testing.B) {
assert.Equal(b, int64(10000000000000000), account.Balance) assert.Equal(b, int64(10000000000000000), account.Balance)
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
util.ExecBlock(mock33.GetClient(), block0.StateHash, block, false, true) util.ExecBlock(mock33.GetClient(), block0.StateHash, block, false, true, false)
} }
} }
...@@ -363,7 +365,7 @@ func TestExecLocalSameTime1(t *testing.T) { ...@@ -363,7 +365,7 @@ func TestExecLocalSameTime1(t *testing.T) {
txs = append(txs, util.CreateTxWithExecer(priv1, "demo2")) txs = append(txs, util.CreateTxWithExecer(priv1, "demo2"))
txs = append(txs, util.CreateTxWithExecer(priv1, "demo2")) txs = append(txs, util.CreateTxWithExecer(priv1, "demo2"))
block2 := util.CreateNewBlock(block, txs) block2 := util.CreateNewBlock(block, txs)
detail, _, err := util.ExecBlock(mock33.GetClient(), block.StateHash, block2, false, true) detail, _, err := util.ExecBlock(mock33.GetClient(), block.StateHash, block2, false, true, false)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
...@@ -393,7 +395,7 @@ func TestExecLocalSameTime0(t *testing.T) { ...@@ -393,7 +395,7 @@ func TestExecLocalSameTime0(t *testing.T) {
txs = append(txs, util.CreateTxWithExecer(priv1, "demo2")) txs = append(txs, util.CreateTxWithExecer(priv1, "demo2"))
txs = append(txs, util.CreateTxWithExecer(priv1, "demo2")) txs = append(txs, util.CreateTxWithExecer(priv1, "demo2"))
block2 := util.CreateNewBlock(block, txs) block2 := util.CreateNewBlock(block, txs)
detail, _, err := util.ExecBlock(mock33.GetClient(), block.StateHash, block2, false, true) detail, _, err := util.ExecBlock(mock33.GetClient(), block.StateHash, block2, false, true, false)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
...@@ -426,7 +428,7 @@ func TestExecLocalSameTimeSetErrKey(t *testing.T) { ...@@ -426,7 +428,7 @@ func TestExecLocalSameTimeSetErrKey(t *testing.T) {
txs = append(txs, util.CreateTxWithExecer(priv1, "demo2")) txs = append(txs, util.CreateTxWithExecer(priv1, "demo2"))
txs = append(txs, util.CreateTxWithExecer(priv1, "demo2")) txs = append(txs, util.CreateTxWithExecer(priv1, "demo2"))
block2 := util.CreateNewBlock(block, txs) block2 := util.CreateNewBlock(block, txs)
detail, _, err := util.ExecBlock(mock33.GetClient(), block.StateHash, block2, false, true) detail, _, err := util.ExecBlock(mock33.GetClient(), block.StateHash, block2, false, true, false)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
......
...@@ -5,10 +5,13 @@ ...@@ -5,10 +5,13 @@
package solo package solo
import ( import (
"sync"
"testing" "testing"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/util" "github.com/33cn/chain33/util"
"github.com/33cn/chain33/util/testnode" "github.com/33cn/chain33/util/testnode"
"github.com/stretchr/testify/assert"
//加载系统内置store, 不要依赖plugin //加载系统内置store, 不要依赖plugin
_ "github.com/33cn/chain33/system/dapp/init" _ "github.com/33cn/chain33/system/dapp/init"
...@@ -31,3 +34,35 @@ func TestSolo(t *testing.T) { ...@@ -31,3 +34,35 @@ func TestSolo(t *testing.T) {
} }
mock33.WaitHeight(2) mock33.WaitHeight(2)
} }
func BenchmarkSolo(b *testing.B) {
cfg, subcfg := testnode.GetDefaultConfig()
solocfg, err := types.ModifySubConfig(subcfg.Consensus["solo"], "waitTxMs", 1000)
assert.Nil(b, err)
subcfg.Consensus["solo"] = solocfg
mock33 := testnode.NewWithConfig(cfg, subcfg, nil)
defer mock33.Close()
txs := util.GenCoinsTxs(mock33.GetGenesisKey(), int64(b.N))
var last []byte
var mu sync.Mutex
b.ResetTimer()
done := make(chan struct{}, 10)
for i := 0; i < 10; i++ {
go func(index int) {
for n := index; n < b.N; n += 10 {
reply, err := mock33.GetAPI().SendTx(txs[n])
if err != nil {
assert.Nil(b, err)
}
mu.Lock()
last = reply.GetMsg()
mu.Unlock()
}
done <- struct{}{}
}(i)
}
for i := 0; i < 10; i++ {
<-done
}
mock33.WaitTx(last)
}
...@@ -76,13 +76,7 @@ func (c *CoinsType) GetTypeMap() map[string]int32 { ...@@ -76,13 +76,7 @@ func (c *CoinsType) GetTypeMap() map[string]int32 {
//DecodePayloadValue 为了性能考虑,coins 是最常用的合约,我们这里不用反射吗,做了特殊化的优化 //DecodePayloadValue 为了性能考虑,coins 是最常用的合约,我们这里不用反射吗,做了特殊化的优化
func (c *CoinsType) DecodePayloadValue(tx *types.Transaction) (string, reflect.Value, error) { func (c *CoinsType) DecodePayloadValue(tx *types.Transaction) (string, reflect.Value, error) {
if txc, ok := types.TxCacheGet(tx); ok {
return txc.GetPayloadValue()
}
txc := types.NewTransactionCache(tx)
name, value, err := c.decodePayloadValue(tx) name, value, err := c.decodePayloadValue(tx)
txc.SetPayloadValue(name, value, err)
types.TxCacheSet(tx, txc)
return name, value, err return name, value, err
} }
......
package types
var gbuffer *buffer
//系统并非线程安全
func init() {
gbuffer = newBuffer(20 * 1024 * 1024)
}
//Buffer 一个连续的byte 空间,永远不会被释放
type buffer struct {
data []byte
offset int
}
//新建一个buffer 对象
func newBuffer(total int) *buffer {
return &buffer{data: make([]byte, total), offset: 0}
}
//BufferReset 重置buffer
func BufferReset() {
gbuffer.offset = 0
}
//BufferAlloc 部分空间
func BufferAlloc(size int) []byte {
if gbuffer.offset+size > 0 {
return make([]byte, size)
}
b := gbuffer.data[gbuffer.offset : gbuffer.offset+size]
gbuffer.offset += size
return b
}
//BufferAllocCap alloc cap
func BufferAllocCap(size int) []byte {
if gbuffer.offset+size > 0 {
return make([]byte, 0, size)
}
b := gbuffer.data[gbuffer.offset:gbuffer.offset]
gbuffer.offset += size
return b
}
package types
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestAlloc(t *testing.T) {
BufferReset()
data := BufferAlloc(10)
assert.Equal(t, 10, len(data))
data2 := BufferAlloc(10)
assert.Equal(t, 10, len(data2))
data3 := BufferAllocCap(10)
assert.Equal(t, 0, len(data3))
data4 := BufferAllocCap(10)
assert.Equal(t, 0, len(data4))
for i := range data {
data[i] = 1
}
for i := range data2 {
data2[i] = 2
}
for i := range data {
assert.Equal(t, byte(1), data[i])
}
for i := range data2 {
assert.Equal(t, byte(2), data2[i])
}
}
func BenchmarkAlloc(b *testing.B) {
BufferReset()
data := make([][]byte, b.N)
for i := 0; i < b.N; i++ {
a := BufferAlloc(10)
if a == nil {
panic("alloc")
}
data[i] = a
}
}
func BenchmarkAllocMake(b *testing.B) {
data := make([][]byte, b.N)
for i := 0; i < b.N; i++ {
a := make([]byte, 10)
if a == nil {
panic("alloc")
}
data[i] = a
}
}
...@@ -508,13 +508,7 @@ func (base *ExecTypeBase) DecodePayload(tx *Transaction) (Message, error) { ...@@ -508,13 +508,7 @@ func (base *ExecTypeBase) DecodePayload(tx *Transaction) (Message, error) {
//DecodePayloadValue 解析tx交易中的payload具体Value值 //DecodePayloadValue 解析tx交易中的payload具体Value值
func (base *ExecTypeBase) DecodePayloadValue(tx *Transaction) (string, reflect.Value, error) { func (base *ExecTypeBase) DecodePayloadValue(tx *Transaction) (string, reflect.Value, error) {
if txc, ok := txCache.Get(tx); ok {
return txc.(*TransactionCache).GetPayloadValue()
}
txc := NewTransactionCache(tx)
name, value, err := base.decodePayloadValue(tx) name, value, err := base.decodePayloadValue(tx)
txc.SetPayloadValue(name, value, err)
txCache.Add(tx, txc)
return name, value, err return name, value, err
} }
......
...@@ -207,3 +207,10 @@ func TestParseExpire(t *testing.T) { ...@@ -207,3 +207,10 @@ func TestParseExpire(t *testing.T) {
assert.Equal(t, int64(123000000000), exp) assert.Equal(t, int64(123000000000), exp)
} }
func BenchmarkHash(b *testing.B) {
tx := &Transaction{Payload: []byte("xxxxxxxxxxxxdggrgrgrgrgrgrgrrhthththhth"), Execer: []byte("hello")}
for i := 0; i < b.N; i++ {
tx.Hash()
}
}
...@@ -43,7 +43,7 @@ singleMode=true ...@@ -43,7 +43,7 @@ singleMode=true
batchsync=false batchsync=false
isRecordBlockSequence=true isRecordBlockSequence=true
isParaChain=false isParaChain=false
enableTxQuickIndex=false enableTxQuickIndex=true
[p2p] [p2p]
seeds=[] seeds=[]
...@@ -68,9 +68,9 @@ grpcFuncWhitelist=["*"] ...@@ -68,9 +68,9 @@ grpcFuncWhitelist=["*"]
[mempool] [mempool]
name="timeline" name="timeline"
poolCacheSize=10240 poolCacheSize=102400
minTxFee=100000 minTxFee=100000
maxTxNumPerAccount=10000 maxTxNumPerAccount=100000
[consensus] [consensus]
name="solo" name="solo"
...@@ -89,7 +89,7 @@ futureBlockTime = 16 ...@@ -89,7 +89,7 @@ futureBlockTime = 16
ticketFrozenTime = 5 ticketFrozenTime = 5
ticketWithdrawTime = 10 ticketWithdrawTime = 10
ticketMinerWaitTime = 2 ticketMinerWaitTime = 2
maxTxNumber = 1600 maxTxNumber = 10000
targetTimespan = 2304 targetTimespan = 2304
targetTimePerBlock = 16 targetTimePerBlock = 16
......
...@@ -32,7 +32,7 @@ func init() { ...@@ -32,7 +32,7 @@ func init() {
rand.Seed(types.Now().UnixNano()) rand.Seed(types.Now().UnixNano())
} }
var chainlog = log15.New("module", "util") var ulog = log15.New("module", "util")
//GetParaExecName : 如果 name 没有 paraName 前缀,那么加上这个前缀 //GetParaExecName : 如果 name 没有 paraName 前缀,那么加上这个前缀
func GetParaExecName(paraName string, name string) string { func GetParaExecName(paraName string, name string) string {
...@@ -220,15 +220,15 @@ func CreateCoinsBlock(priv crypto.PrivKey, n int64) *types.Block { ...@@ -220,15 +220,15 @@ func CreateCoinsBlock(priv crypto.PrivKey, n int64) *types.Block {
} }
// ExecBlock : just exec block // ExecBlock : just exec block
func ExecBlock(client queue.Client, prevStateRoot []byte, block *types.Block, errReturn bool, sync bool) (*types.BlockDetail, []*types.Transaction, error) { func ExecBlock(client queue.Client, prevStateRoot []byte, block *types.Block, errReturn, sync, checkblock bool) (*types.BlockDetail, []*types.Transaction, error) {
//发送执行交易给execs模块 //发送执行交易给execs模块
//通过consensus module 再次检查 //通过consensus module 再次检查
ulog := chainlog
ulog.Debug("ExecBlock", "height------->", block.Height, "ntx", len(block.Txs)) ulog.Debug("ExecBlock", "height------->", block.Height, "ntx", len(block.Txs))
beg := types.Now() beg := types.Now()
defer func() { defer func() {
ulog.Info("ExecBlock", "height", block.Height, "ntx", len(block.Txs), "writebatchsync", sync, "cost", types.Since(beg)) ulog.Info("ExecBlock", "height", block.Height, "ntx", len(block.Txs), "writebatchsync", sync, "cost", types.Since(beg))
}() }()
if errReturn && block.Height > 0 && !block.CheckSign() { if errReturn && block.Height > 0 && !block.CheckSign() {
//block的来源不是自己的mempool,而是别人的区块 //block的来源不是自己的mempool,而是别人的区块
return nil, nil, types.ErrSign return nil, nil, types.ErrSign
...@@ -241,18 +241,21 @@ func ExecBlock(client queue.Client, prevStateRoot []byte, block *types.Block, er ...@@ -241,18 +241,21 @@ func ExecBlock(client queue.Client, prevStateRoot []byte, block *types.Block, er
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
ulog.Info("ExecBlock", "CheckTxDup", types.Since(beg))
beg = types.Now()
newtxscount := len(cacheTxs) newtxscount := len(cacheTxs)
if oldtxscount != newtxscount && errReturn { if oldtxscount != newtxscount && errReturn {
return nil, nil, types.ErrTxDup return nil, nil, types.ErrTxDup
} }
ulog.Debug("ExecBlock", "prevtx", oldtxscount, "newtx", newtxscount) ulog.Debug("ExecBlock", "prevtx", oldtxscount, "newtx", newtxscount)
block.TxHash = merkle.CalcMerkleRootCache(cacheTxs)
block.Txs = types.CacheToTxs(cacheTxs) block.Txs = types.CacheToTxs(cacheTxs)
//println("1")
receipts, err := ExecTx(client, prevStateRoot, block) receipts, err := ExecTx(client, prevStateRoot, block)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
ulog.Info("ExecBlock", "ExecTx", types.Since(beg))
beg = types.Now()
var kvset []*types.KeyValue var kvset []*types.KeyValue
var deltxlist = make(map[int]bool) var deltxlist = make(map[int]bool)
var rdata []*types.ReceiptData //save to db receipt log var rdata []*types.ReceiptData //save to db receipt log
...@@ -270,34 +273,45 @@ func ExecBlock(client queue.Client, prevStateRoot []byte, block *types.Block, er ...@@ -270,34 +273,45 @@ func ExecBlock(client queue.Client, prevStateRoot []byte, block *types.Block, er
kvset = append(kvset, receipt.KV...) kvset = append(kvset, receipt.KV...)
} }
kvset = DelDupKey(kvset) kvset = DelDupKey(kvset)
//check TxHash
calcHash := merkle.CalcMerkleRoot(block.Txs)
if errReturn && !bytes.Equal(calcHash, block.TxHash) {
return nil, nil, types.ErrCheckTxHash
}
block.TxHash = calcHash
//删除无效的交易 //删除无效的交易
var deltx []*types.Transaction var deltx []*types.Transaction
if len(deltxlist) > 0 { if len(deltxlist) > 0 {
var newtx []*types.Transaction index := 0
for i := 0; i < len(block.Txs); i++ { for i := 0; i < len(block.Txs); i++ {
if deltxlist[i] { if deltxlist[i] {
deltx = append(deltx, block.Txs[i]) deltx = append(deltx, block.Txs[i])
} else { continue
newtx = append(newtx, block.Txs[i])
} }
block.Txs[index] = block.Txs[i]
cacheTxs[index] = cacheTxs[i]
index++
} }
block.Txs = newtx block.Txs = block.Txs[0:index]
block.TxHash = merkle.CalcMerkleRoot(block.Txs) cacheTxs = cacheTxs[0:index]
} }
//交易有执行不成功的,报错(TxHash一定不同)
if len(deltx) > 0 && errReturn {
return nil, nil, types.ErrCheckTxHash
}
//检查block的txhash值
calcHash := merkle.CalcMerkleRootCache(cacheTxs)
if errReturn && !bytes.Equal(calcHash, block.TxHash) {
return nil, nil, types.ErrCheckTxHash
}
ulog.Info("ExecBlock", "CalcMerkleRootCache", types.Since(beg))
beg = types.Now()
block.TxHash = calcHash
var detail types.BlockDetail var detail types.BlockDetail
calcHash, err = ExecKVMemSet(client, prevStateRoot, block.Height, kvset, sync) calcHash, err = ExecKVMemSet(client, prevStateRoot, block.Height, kvset, sync)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
//println("2")
if errReturn && !bytes.Equal(block.StateHash, calcHash) { if errReturn && !bytes.Equal(block.StateHash, calcHash) {
ExecKVSetRollback(client, calcHash) err = ExecKVSetRollback(client, calcHash)
if err != nil {
ulog.Error("execBlock-->ExecKVSetRollback", "err", err)
}
if len(rdata) > 0 { if len(rdata) > 0 {
for i, rd := range rdata { for i, rd := range rdata {
rd.OutputReceiptDetails(block.Txs[i].Execer, ulog) rd.OutputReceiptDetails(block.Txs[i].Execer, ulog)
...@@ -308,7 +322,22 @@ func ExecBlock(client queue.Client, prevStateRoot []byte, block *types.Block, er ...@@ -308,7 +322,22 @@ func ExecBlock(client queue.Client, prevStateRoot []byte, block *types.Block, er
block.StateHash = calcHash block.StateHash = calcHash
detail.Block = block detail.Block = block
detail.Receipts = rdata detail.Receipts = rdata
ExecKVSetCommit(client, block.StateHash) if detail.Block.Height > 0 && checkblock {
err := CheckBlock(client, &detail)
if err != nil {
ulog.Debug("CheckBlock-->", "err=", err)
return nil, deltx, err
}
}
ulog.Info("ExecBlock", "CheckBlock", types.Since(beg))
beg = types.Now()
// 写数据库失败时需要及时返回错误,防止错误数据被写入localdb中CHAIN33-567
err = ExecKVSetCommit(client, block.StateHash)
if err != nil {
return nil, nil, err
}
detail.KV = kvset
detail.PrevStatusHash = prevStateRoot
return &detail, deltx, nil return &detail, deltx, nil
} }
...@@ -362,7 +391,7 @@ func ExecAndCheckBlock2(qclient queue.Client, block *types.Block, txs []*types.T ...@@ -362,7 +391,7 @@ func ExecAndCheckBlock2(qclient queue.Client, block *types.Block, txs []*types.T
//ExecAndCheckBlockCB : //ExecAndCheckBlockCB :
func ExecAndCheckBlockCB(qclient queue.Client, block *types.Block, txs []*types.Transaction, cb func(int, *types.ReceiptData) error) (*types.Block, error) { func ExecAndCheckBlockCB(qclient queue.Client, block *types.Block, txs []*types.Transaction, cb func(int, *types.ReceiptData) error) (*types.Block, error) {
block2 := CreateNewBlock(block, txs) block2 := CreateNewBlock(block, txs)
detail, deltx, err := ExecBlock(qclient, block.StateHash, block2, false, true) detail, deltx, err := ExecBlock(qclient, block.StateHash, block2, false, true, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -410,7 +439,7 @@ func ResetDatadir(cfg *types.Config, datadir string) string { ...@@ -410,7 +439,7 @@ func ResetDatadir(cfg *types.Config, datadir string) string {
} }
datadir = filepath.Join(dir, datadir[6:]) datadir = filepath.Join(dir, datadir[6:])
} }
chainlog.Info("current user data dir is ", "dir", datadir) ulog.Info("current user data dir is ", "dir", datadir)
cfg.Log.LogFile = filepath.Join(datadir, cfg.Log.LogFile) cfg.Log.LogFile = filepath.Join(datadir, cfg.Log.LogFile)
cfg.BlockChain.DbPath = filepath.Join(datadir, cfg.BlockChain.DbPath) cfg.BlockChain.DbPath = filepath.Join(datadir, cfg.BlockChain.DbPath)
cfg.P2P.DbPath = filepath.Join(datadir, cfg.P2P.DbPath) cfg.P2P.DbPath = filepath.Join(datadir, cfg.P2P.DbPath)
......
...@@ -40,31 +40,35 @@ func (c *Cache) Purge() { ...@@ -40,31 +40,35 @@ func (c *Cache) Purge() {
// Add adds a value to the cache. Returns true if an eviction occurred. // Add adds a value to the cache. Returns true if an eviction occurred.
func (c *Cache) Add(key, value interface{}) (evicted bool) { func (c *Cache) Add(key, value interface{}) (evicted bool) {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() evicted = c.lru.Add(key, value)
return c.lru.Add(key, value) c.lock.Unlock()
return evicted
} }
// Get looks up a key's value from the cache. // Get looks up a key's value from the cache.
func (c *Cache) Get(key interface{}) (value interface{}, ok bool) { func (c *Cache) Get(key interface{}) (value interface{}, ok bool) {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() value, ok = c.lru.Get(key)
return c.lru.Get(key) c.lock.Unlock()
return value, ok
} }
// Contains checks if a key is in the cache, without updating the // Contains checks if a key is in the cache, without updating the
// recent-ness or deleting it for being stale. // recent-ness or deleting it for being stale.
func (c *Cache) Contains(key interface{}) bool { func (c *Cache) Contains(key interface{}) bool {
c.lock.RLock() c.lock.RLock()
defer c.lock.RUnlock() containKey := c.lru.Contains(key)
return c.lru.Contains(key) c.lock.RUnlock()
return containKey
} }
// Peek returns the key value (or undefined if not found) without updating // Peek returns the key value (or undefined if not found) without updating
// the "recently used"-ness of the key. // the "recently used"-ness of the key.
func (c *Cache) Peek(key interface{}) (value interface{}, ok bool) { func (c *Cache) Peek(key interface{}) (value interface{}, ok bool) {
c.lock.RLock() c.lock.RLock()
defer c.lock.RUnlock() value, ok = c.lru.Peek(key)
return c.lru.Peek(key) c.lock.RUnlock()
return value, ok
} }
// ContainsOrAdd checks if a key is in the cache without updating the // ContainsOrAdd checks if a key is in the cache without updating the
...@@ -98,13 +102,15 @@ func (c *Cache) RemoveOldest() { ...@@ -98,13 +102,15 @@ func (c *Cache) RemoveOldest() {
// Keys returns a slice of the keys in the cache, from oldest to newest. // Keys returns a slice of the keys in the cache, from oldest to newest.
func (c *Cache) Keys() []interface{} { func (c *Cache) Keys() []interface{} {
c.lock.RLock() c.lock.RLock()
defer c.lock.RUnlock() keys := c.lru.Keys()
return c.lru.Keys() c.lock.RUnlock()
return keys
} }
// Len returns the number of items in the cache. // Len returns the number of items in the cache.
func (c *Cache) Len() int { func (c *Cache) Len() int {
c.lock.RLock() c.lock.RLock()
defer c.lock.RUnlock() length := c.lru.Len()
return c.lru.Len() c.lock.RUnlock()
return length
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment