Commit c7437c84 authored by vipwzw's avatar vipwzw Committed by 33cn

update chain33 0305

parent c4acd637
...@@ -9,6 +9,8 @@ datadir* ...@@ -9,6 +9,8 @@ datadir*
*.bak *.bak
.idea .idea
.vscode .vscode
*.pprof
*.test
cmd/chain33/chain33 cmd/chain33/chain33
cmd/tools/tools cmd/tools/tools
build/cert.pem build/cert.pem
......
...@@ -16,7 +16,6 @@ package account ...@@ -16,7 +16,6 @@ package account
//8. gen a private key -> private key to address (bitcoin likes) //8. gen a private key -> private key to address (bitcoin likes)
import ( import (
"fmt"
"strings" "strings"
"github.com/33cn/chain33/client" "github.com/33cn/chain33/client"
...@@ -37,6 +36,7 @@ type DB struct { ...@@ -37,6 +36,7 @@ type DB struct {
execAccountKeyPerfix []byte execAccountKeyPerfix []byte
execer string execer string
symbol string symbol string
accountKeyBuffer []byte
} }
// NewCoinsAccount 新建账户 // NewCoinsAccount 新建账户
...@@ -64,6 +64,8 @@ func NewAccountDB(execer string, symbol string, db dbm.KV) (*DB, error) { ...@@ -64,6 +64,8 @@ func NewAccountDB(execer string, symbol string, db dbm.KV) (*DB, error) {
func newAccountDB(prefix string) *DB { func newAccountDB(prefix string) *DB {
acc := &DB{} acc := &DB{}
acc.accountKeyPerfix = []byte(prefix) acc.accountKeyPerfix = []byte(prefix)
acc.accountKeyBuffer = make([]byte, 0, len(acc.accountKeyPerfix)+64)
acc.accountKeyBuffer = append(acc.accountKeyBuffer, acc.accountKeyPerfix...)
acc.execAccountKeyPerfix = append([]byte(prefix), []byte("exec-")...) acc.execAccountKeyPerfix = append([]byte(prefix), []byte("exec-")...)
//alog.Warn("NewAccountDB", "prefix", prefix, "key1", string(acc.accountKeyPerfix), "key2", string(acc.execAccountKeyPerfix)) //alog.Warn("NewAccountDB", "prefix", prefix, "key1", string(acc.accountKeyPerfix), "key2", string(acc.execAccountKeyPerfix))
return acc return acc
...@@ -75,9 +77,15 @@ func (acc *DB) SetDB(db dbm.KV) *DB { ...@@ -75,9 +77,15 @@ func (acc *DB) SetDB(db dbm.KV) *DB {
return acc return acc
} }
func (acc *DB) accountReadKey(addr string) []byte {
acc.accountKeyBuffer = acc.accountKeyBuffer[0:len(acc.accountKeyPerfix)]
acc.accountKeyBuffer = append(acc.accountKeyBuffer, []byte(addr)...)
return acc.accountKeyBuffer
}
// LoadAccount 根据地址载入账户 // LoadAccount 根据地址载入账户
func (acc *DB) LoadAccount(addr string) *types.Account { func (acc *DB) LoadAccount(addr string) *types.Account {
value, err := acc.db.Get(acc.AccountKey(addr)) value, err := acc.db.Get(acc.accountReadKey(addr))
if err != nil { if err != nil {
return &types.Account{Addr: addr} return &types.Account{Addr: addr}
} }
...@@ -127,10 +135,11 @@ func (acc *DB) Transfer(from, to string, amount int64) (*types.Receipt, error) { ...@@ -127,10 +135,11 @@ func (acc *DB) Transfer(from, to string, amount int64) (*types.Receipt, error) {
Prev: &copyto, Prev: &copyto,
Current: accTo, Current: accTo,
} }
fromkv := acc.GetKVSet(accFrom)
acc.SaveAccount(accFrom) tokv := acc.GetKVSet(accTo)
acc.SaveAccount(accTo) acc.SaveKVSet(fromkv)
return acc.transferReceipt(accFrom, accTo, receiptBalanceFrom, receiptBalanceTo), nil acc.SaveKVSet(tokv)
return acc.transferReceipt(fromkv, tokv, receiptBalanceFrom, receiptBalanceTo), nil
} }
return nil, types.ErrNoBalance return nil, types.ErrNoBalance
...@@ -147,12 +156,12 @@ func (acc *DB) depositBalance(execaddr string, amount int64) (*types.Receipt, er ...@@ -147,12 +156,12 @@ func (acc *DB) depositBalance(execaddr string, amount int64) (*types.Receipt, er
Prev: &copyacc, Prev: &copyacc,
Current: acc1, Current: acc1,
} }
acc.SaveAccount(acc1) kv := acc.GetKVSet(acc1)
acc.SaveKVSet(kv)
log1 := &types.ReceiptLog{ log1 := &types.ReceiptLog{
Ty: int32(types.TyLogDeposit), Ty: int32(types.TyLogDeposit),
Log: types.Encode(receiptBalance), Log: types.Encode(receiptBalance),
} }
kv := acc.GetKVSet(acc1)
return &types.Receipt{ return &types.Receipt{
Ty: types.ExecOk, Ty: types.ExecOk,
KV: kv, KV: kv,
...@@ -160,7 +169,7 @@ func (acc *DB) depositBalance(execaddr string, amount int64) (*types.Receipt, er ...@@ -160,7 +169,7 @@ func (acc *DB) depositBalance(execaddr string, amount int64) (*types.Receipt, er
}, nil }, nil
} }
func (acc *DB) transferReceipt(accFrom, accTo *types.Account, receiptFrom, receiptTo proto.Message) *types.Receipt { func (acc *DB) transferReceipt(fromkv, tokv []*types.KeyValue, receiptFrom, receiptTo proto.Message) *types.Receipt {
ty := int32(types.TyLogTransfer) ty := int32(types.TyLogTransfer)
log1 := &types.ReceiptLog{ log1 := &types.ReceiptLog{
Ty: ty, Ty: ty,
...@@ -170,8 +179,9 @@ func (acc *DB) transferReceipt(accFrom, accTo *types.Account, receiptFrom, recei ...@@ -170,8 +179,9 @@ func (acc *DB) transferReceipt(accFrom, accTo *types.Account, receiptFrom, recei
Ty: ty, Ty: ty,
Log: types.Encode(receiptTo), Log: types.Encode(receiptTo),
} }
kv := acc.GetKVSet(accFrom) kv := make([]*types.KeyValue, 0, len(fromkv)+len(tokv))
kv = append(kv, acc.GetKVSet(accTo)...) kv = append(kv, fromkv...)
kv = append(kv, tokv...)
return &types.Receipt{ return &types.Receipt{
Ty: types.ExecOk, Ty: types.ExecOk,
KV: kv, KV: kv,
...@@ -187,13 +197,21 @@ func (acc *DB) SaveAccount(acc1 *types.Account) { ...@@ -187,13 +197,21 @@ func (acc *DB) SaveAccount(acc1 *types.Account) {
} }
} }
//SaveKVSet 保存Key Value set
func (acc *DB) SaveKVSet(set []*types.KeyValue) {
for i := 0; i < len(set); i++ {
acc.db.Set(set[i].GetKey(), set[i].Value)
}
}
// GetKVSet 将账户数据转为数据库存储kv // GetKVSet 将账户数据转为数据库存储kv
func (acc *DB) GetKVSet(acc1 *types.Account) (kvset []*types.KeyValue) { func (acc *DB) GetKVSet(acc1 *types.Account) (kvset []*types.KeyValue) {
value := types.Encode(acc1) value := types.Encode(acc1)
kvset = append(kvset, &types.KeyValue{ kvset = make([]*types.KeyValue, 1)
kvset[0] = &types.KeyValue{
Key: acc.AccountKey(acc1.Addr), Key: acc.AccountKey(acc1.Addr),
Value: value, Value: value,
}) }
return kvset return kvset
} }
...@@ -218,17 +236,18 @@ func (acc *DB) LoadAccountsDB(addrs []string) (accs []*types.Account, err error) ...@@ -218,17 +236,18 @@ func (acc *DB) LoadAccountsDB(addrs []string) (accs []*types.Account, err error)
// AccountKey return the key of address in DB // AccountKey return the key of address in DB
func (acc *DB) AccountKey(address string) (key []byte) { func (acc *DB) AccountKey(address string) (key []byte) {
key = make([]byte, 0, len(acc.accountKeyPerfix)+len(address))
key = append(key, acc.accountKeyPerfix...) key = append(key, acc.accountKeyPerfix...)
key = append(key, []byte(address)...) key = append(key, []byte(address)...)
return key return key
} }
func symbolPrefix(execer string, symbol string) string { func symbolPrefix(execer string, symbol string) string {
return fmt.Sprintf("mavl-%s-%s-", execer, symbol) return "mavl-" + execer + "-" + symbol + "-"
} }
func symbolExecPrefix(execer string, symbol string) string { func symbolExecPrefix(execer string, symbol string) string {
return fmt.Sprintf("mavl-%s-%s-exec", execer, symbol) return "mavl-" + execer + "-" + symbol + "-exec"
} }
// GetTotalCoins 获取代币总量 // GetTotalCoins 获取代币总量
......
...@@ -52,6 +52,7 @@ func (acc *DB) GetExecKVSet(execaddr string, acc1 *types.Account) (kvset []*type ...@@ -52,6 +52,7 @@ func (acc *DB) GetExecKVSet(execaddr string, acc1 *types.Account) (kvset []*type
} }
func (acc *DB) execAccountKey(address, execaddr string) (key []byte) { func (acc *DB) execAccountKey(address, execaddr string) (key []byte) {
key = make([]byte, 0, len(acc.execAccountKeyPerfix)+len(execaddr)+len(address)+1)
key = append(key, acc.execAccountKeyPerfix...) key = append(key, acc.execAccountKeyPerfix...)
key = append(key, []byte(execaddr)...) key = append(key, []byte(execaddr)...)
key = append(key, []byte(":")...) key = append(key, []byte(":")...)
......
...@@ -7,7 +7,6 @@ import ( ...@@ -7,7 +7,6 @@ import (
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
) )
func (chain *BlockChain) procLocalDB(msgtype int64, msg *queue.Message, reqnum chan struct{}) bool { func (chain *BlockChain) procLocalDB(msgtype int64, msg *queue.Message, reqnum chan struct{}) bool {
switch msgtype { switch msgtype {
case types.EventLocalGet: case types.EventLocalGet:
......
...@@ -23,57 +23,92 @@ callerFile = false ...@@ -23,57 +23,92 @@ callerFile = false
callerFunction = false callerFunction = false
[blockchain] [blockchain]
# 数据库文件目录
dbPath="datadir" dbPath="datadir"
# 数据库缓存大小
dbCache=64 dbCache=64
# 同步区块批量写数据库时,是否需要立即写磁盘,非固态硬盘的电脑可以设置为false,以提高性能
batchsync=false batchsync=false
# 是否记录添加或者删除区块的序列,若节点作为主链节点,为平行链节点提供服务,需要设置为true
isRecordBlockSequence=false isRecordBlockSequence=false
enableTxQuickIndex=false enableTxQuickIndex=false
[p2p] [p2p]
# P2P服务监听端口号
port=13802 port=13802
# 种子节点,格式为ip:port,多个节点以逗号分隔,如seeds=["10.0.0.1:13802","10.0.0.2:13802","10.0.0.3:13802"]
seeds=[] seeds=[]
# 是否为种子节点
isSeed=false isSeed=false
# 是否使用内置的种子节点
innerSeedEnable=true innerSeedEnable=true
# 是否使用Github获取种子节点
useGithub=true useGithub=true
# 最多的接入节点个数
innerBounds=300 innerBounds=300
# 数据库文件目录
dbPath="datadir/addrbook" dbPath="datadir/addrbook"
# 数据库缓存大小
dbCache=4 dbCache=4
# GRPC请求日志文件
grpcLogFile="grpc33.log" grpcLogFile="grpc33.log"
[rpc] [rpc]
# jrpc绑定地址
jrpcBindAddr="localhost:8801" jrpcBindAddr="localhost:8801"
# grpc绑定地址
grpcBindAddr="localhost:8802" grpcBindAddr="localhost:8802"
# 白名单列表,允许访问的IP地址,默认是“*”,允许所有IP访问
whitelist=["127.0.0.1"] whitelist=["127.0.0.1"]
# jrpc方法请求白名单,默认是“*”,允许访问所有RPC方法
jrpcFuncWhitelist=["*"] jrpcFuncWhitelist=["*"]
# grpc方法请求白名单,默认是“*”,允许访问所有RPC方法
grpcFuncWhitelist=["*"] grpcFuncWhitelist=["*"]
# 是否开启https
enableTLS=false enableTLS=false
# 证书文件,证书和私钥文件可以用cli工具生成
certFile="cert.pem" certFile="cert.pem"
# 私钥文件
keyFile="key.pem" keyFile="key.pem"
[mempool] [mempool]
# 每个账户在mempool中得最大交易数量,默认100
maxTxNumPerAccount=100 maxTxNumPerAccount=100
[store] [store]
# 数据文件存储路径
dbPath="datadir/mavltree" dbPath="datadir/mavltree"
# Cache大小
dbCache=128 dbCache=128
[store.sub.mavl] [store.sub.mavl]
# 是否使能mavl加前缀
enableMavlPrefix=false enableMavlPrefix=false
# 是否使能MVCC,如果mavl中enableMVCC为true此处必须为true
enableMVCC=false enableMVCC=false
# 是否使能mavl数据裁剪
enableMavlPrune=false enableMavlPrune=false
# 裁剪高度间隔
pruneHeight=10000 pruneHeight=10000
[wallet] [wallet]
# walletdb路径
dbPath="wallet" dbPath="wallet"
# walletdb缓存大小
dbCache=16 dbCache=16
[wallet.sub.ticket] [wallet.sub.ticket]
# 是否关闭ticket自动挖矿,默认false
minerdisable=false minerdisable=false
# 允许购买ticket挖矿的白名单地址,默认配置“*”,允许所有地址购买
minerwhitelist=["*"] minerwhitelist=["*"]
[exec] [exec]
#是否开启stat插件
enableStat=false enableStat=false
#是否开启MVCC插件
enableMVCC=false enableMVCC=false
[exec.sub.token] [exec.sub.token]
#是否保存token交易信息
saveTokenTxList=false saveTokenTxList=false
...@@ -24,55 +24,91 @@ callerFile = false ...@@ -24,55 +24,91 @@ callerFile = false
callerFunction = false callerFunction = false
[blockchain] [blockchain]
# 缓存区块的个数
defCacheSize=128 defCacheSize=128
# 同步区块时一次最多申请获取的区块个数
maxFetchBlockNum=128 maxFetchBlockNum=128
# 向对端节点请求同步区块的时间间隔
timeoutSeconds=5 timeoutSeconds=5
batchBlockNum=128 batchBlockNum=128
# 使用的数据库类型
driver="leveldb" driver="leveldb"
# 数据库文件目录
dbPath="datadir" dbPath="datadir"
# 数据库缓存大小
dbCache=64 dbCache=64
isStrongConsistency=false isStrongConsistency=false
# 是否为单节点
singleMode=true singleMode=true
# 同步区块批量写数据库时,是否需要立即写磁盘,非固态硬盘的电脑可以设置为false,以提高性能
batchsync=false batchsync=false
# 是否记录添加或者删除区块的序列,若节点作为主链节点,为平行链节点提供服务,需要设置为true
isRecordBlockSequence=true isRecordBlockSequence=true
# 是否为平行链节点
isParaChain=false isParaChain=false
enableTxQuickIndex=false enableTxQuickIndex=false
[p2p] [p2p]
# P2P服务监听端口号
port=13802 port=13802
# 种子节点,格式为ip:port,多个节点以逗号分隔,如seeds=["10.0.0.1:13802","10.0.0.2:13802","10.0.0.3:13802"]
seeds=[] seeds=[]
# 是否启动P2P服务
enable=true enable=true
# 是否为种子节点
isSeed=false isSeed=false
# 是否作为服务端,对外提供服务
serverStart=true serverStart=true
# 是否使用内置的种子节点
innerSeedEnable=true innerSeedEnable=true
# 是否使用Github获取种子节点
useGithub=true useGithub=true
# 最多的接入节点个数
innerBounds=300 innerBounds=300
msgCacheSize=10240 msgCacheSize=10240
# 使用的数据库类型
driver="leveldb" driver="leveldb"
# 使用的数据库类型
dbPath="datadir/addrbook" dbPath="datadir/addrbook"
# 数据库缓存大小
dbCache=4 dbCache=4
# GRPC请求日志文件
grpcLogFile="grpc33.log" grpcLogFile="grpc33.log"
[rpc] [rpc]
# jrpc绑定地址
jrpcBindAddr="localhost:8801" jrpcBindAddr="localhost:8801"
# grpc绑定地址
grpcBindAddr="localhost:8802" grpcBindAddr="localhost:8802"
# 白名单列表,允许访问的IP地址,默认是“*”,允许所有IP访问
whitelist=["127.0.0.1"] whitelist=["127.0.0.1"]
# jrpc方法请求白名单,默认是“*”,允许访问所有RPC方法
jrpcFuncWhitelist=["*"] jrpcFuncWhitelist=["*"]
# grpc方法请求白名单,默认是“*”,允许访问所有RPC方法
grpcFuncWhitelist=["*"] grpcFuncWhitelist=["*"]
# 是否开启https
enableTLS=true enableTLS=true
# 证书文件,证书和私钥文件可以用cli工具生成
certFile="cert.pem" certFile="cert.pem"
# 私钥文件
keyFile="key.pem" keyFile="key.pem"
[mempool] [mempool]
# mempool队列名称,可配,timeline,score,price
name="timeline" name="timeline"
# mempool缓存容量大小,默认10240
poolCacheSize=10240 poolCacheSize=10240
# 最小得交易手续费用,这个没有默认值,必填,一般是100000
minTxFee=100000 minTxFee=100000
# 每个账户在mempool中得最大交易数量,默认100
maxTxNumPerAccount=100 maxTxNumPerAccount=100
[mempool.sub.timeline] [mempool.sub.timeline]
# mempool缓存容量大小,默认10240
poolCacheSize=10240 poolCacheSize=10240
[mempool.sub.score] [mempool.sub.score]
# mempool缓存容量大小,默认10240
poolCacheSize=10240 poolCacheSize=10240
timeParam=1 #时间占价格比例 timeParam=1 #时间占价格比例
priceConstant=1544 #手续费相对于时间的一个合适的常量,取当前unxi时间戳前四位数,排序时手续费高1e-5~=快1s priceConstant=1544 #手续费相对于时间的一个合适的常量,取当前unxi时间戳前四位数,排序时手续费高1e-5~=快1s
...@@ -82,24 +118,39 @@ pricePower=1 #常量比例 ...@@ -82,24 +118,39 @@ pricePower=1 #常量比例
poolCacheSize=10240 poolCacheSize=10240
[consensus] [consensus]
#共识名,可选项有solo,ticket,raft,tendermint,para
name="solo" name="solo"
#是否开启挖矿,开启挖矿才能创建区块
minerstart=true minerstart=true
#创世区块时间(UTC时间)
genesisBlockTime=1514533394 genesisBlockTime=1514533394
#创世交易地址
genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt" genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
[mver.consensus] [mver.consensus]
#基金账户地址
fundKeyAddr = "1BQXS6TxaYYG5mADaWij4AxhZZUTpw95a5" fundKeyAddr = "1BQXS6TxaYYG5mADaWij4AxhZZUTpw95a5"
#用户回报
coinReward = 18 coinReward = 18
#发展基金回报
coinDevFund = 12 coinDevFund = 12
#ticket价格
ticketPrice = 10000 ticketPrice = 10000
#挖矿难度
powLimitBits = "0x1f00ffff" powLimitBits = "0x1f00ffff"
#每次调整难度的最大的范围,如果设置成 4 的话,范围是 (1/4 - 4),一次不能增加 4倍以上的难度,或者难度减少为 原来的 1/4 ,这个参数,是为了难度不会突然爆增加或者减少
retargetAdjustmentFactor = 4 retargetAdjustmentFactor = 4
#表示如果区块时间大于当前时间 16s ,那么区块就会判定为无效区块。
futureBlockTime = 16 futureBlockTime = 16
#ticket冻结时长
ticketFrozenTime = 5 #5s only for test ticketFrozenTime = 5 #5s only for test
ticketWithdrawTime = 10 #10s only for test ticketWithdrawTime = 10 #10s only for test
ticketMinerWaitTime = 2 #2s only for test ticketMinerWaitTime = 2 #2s only for test
#区块包含最多交易数
maxTxNumber = 1600 #160 maxTxNumber = 1600 #160
#调整挖矿难度的间隔,(ps:难度不是每个区块都调整的,而是每隔 targetTimespan / targetTimePerBlock 块调整一次)
targetTimespan = 2304 targetTimespan = 2304
#每个区块打包的目标时间
targetTimePerBlock = 16 targetTimePerBlock = 16
[mver.consensus.ForkChainParamV1] [mver.consensus.ForkChainParamV1]
...@@ -139,38 +190,60 @@ returnAddr="1KcCVZLSQYRUwE5EXTsAoQs9LuJW6xwfQa" ...@@ -139,38 +190,60 @@ returnAddr="1KcCVZLSQYRUwE5EXTsAoQs9LuJW6xwfQa"
count=10000 count=10000
[store] [store]
# 数据存储格式名称,目前支持mavl,kvdb,kvmvcc,mpt
name="mavl" name="mavl"
# 数据存储驱动类别,目前支持leveldb,goleveldb,memdb,gobadgerdb,ssdb,pegasus
driver="leveldb" driver="leveldb"
# 数据文件存储路径
dbPath="datadir/mavltree" dbPath="datadir/mavltree"
# Cache大小
dbCache=128 dbCache=128
# 数据库版本
localdbVersion="1.0.0" localdbVersion="1.0.0"
[store.sub.mavl] [store.sub.mavl]
# 是否使能mavl加前缀
enableMavlPrefix=false enableMavlPrefix=false
# 是否使能MVCC,如果mavl中enableMVCC为true此处必须为true
enableMVCC=false enableMVCC=false
# 是否使能mavl数据裁剪
enableMavlPrune=false enableMavlPrune=false
# 裁剪高度间隔
pruneHeight=10000 pruneHeight=10000
[wallet] [wallet]
# 交易发送最低手续费,单位0.00000001BTY(1e-8),默认100000,即0.001BTY
minFee=100000 minFee=100000
# walletdb驱动名,支持leveldb/memdb/gobadgerdb/ssdb/pegasus
driver="leveldb" driver="leveldb"
# walletdb路径
dbPath="wallet" dbPath="wallet"
# walletdb缓存大小
dbCache=16 dbCache=16
# 钱包发送交易签名方式
signType="secp256k1" signType="secp256k1"
[wallet.sub.ticket] [wallet.sub.ticket]
# 是否关闭ticket自动挖矿,默认false
minerdisable=false minerdisable=false
# 允许购买ticket挖矿的白名单地址,默认配置“*”,允许所有地址购买
minerwhitelist=["*"] minerwhitelist=["*"]
[exec] [exec]
#执行器执行是否免费
isFree=false isFree=false
#执行器执行所需最小费用,低于Mempool和Wallet设置的MinFee,在minExecFee = 0 的情况下,isFree = true才会生效
minExecFee=100000 minExecFee=100000
#是否开启stat插件
enableStat=false enableStat=false
#是否开启MVCC插件
enableMVCC=false enableMVCC=false
alias=["token1:token","token2:token","token3:token"] alias=["token1:token","token2:token","token3:token"]
[exec.sub.token] [exec.sub.token]
#是否保存token交易信息
saveTokenTxList=true saveTokenTxList=true
#token审批人地址
tokenApprs = [ tokenApprs = [
"1Bsg9j6gW83sShoee1fZAt9TkUjcrCgA9S", "1Bsg9j6gW83sShoee1fZAt9TkUjcrCgA9S",
"1Q8hGLfoGe63efeWa8fJ4Pnukhkngt6poK", "1Q8hGLfoGe63efeWa8fJ4Pnukhkngt6poK",
...@@ -189,9 +262,11 @@ cryptoPath="authdir/crypto" ...@@ -189,9 +262,11 @@ cryptoPath="authdir/crypto"
signType="auth_ecdsa" signType="auth_ecdsa"
[exec.sub.relay] [exec.sub.relay]
#relay执行器保存BTC头执行权限地址
genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt" genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
[exec.sub.manage] [exec.sub.manage]
#manage执行器超级管理员地址
superManager=[ superManager=[
"1Bsg9j6gW83sShoee1fZAt9TkUjcrCgA9S", "1Bsg9j6gW83sShoee1fZAt9TkUjcrCgA9S",
"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv", "12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv",
......
...@@ -17,6 +17,7 @@ import ( ...@@ -17,6 +17,7 @@ import (
var addrSeed = []byte("address seed bytes for public key") var addrSeed = []byte("address seed bytes for public key")
var addressCache *lru.Cache var addressCache *lru.Cache
var pubkeyCache *lru.Cache
var checkAddressCache *lru.Cache var checkAddressCache *lru.Cache
var multisignCache *lru.Cache var multisignCache *lru.Cache
var multiCheckAddressCache *lru.Cache var multiCheckAddressCache *lru.Cache
...@@ -38,6 +39,7 @@ const MultiSignVer byte = 5 ...@@ -38,6 +39,7 @@ const MultiSignVer byte = 5
func init() { func init() {
multisignCache, _ = lru.New(10240) multisignCache, _ = lru.New(10240)
pubkeyCache, _ = lru.New(10240)
addressCache, _ = lru.New(10240) addressCache, _ = lru.New(10240)
checkAddressCache, _ = lru.New(10240) checkAddressCache, _ = lru.New(10240)
multiCheckAddressCache, _ = lru.New(10240) multiCheckAddressCache, _ = lru.New(10240)
...@@ -101,6 +103,16 @@ func PubKeyToAddress(in []byte) *Address { ...@@ -101,6 +103,16 @@ func PubKeyToAddress(in []byte) *Address {
return HashToAddress(NormalVer, in) return HashToAddress(NormalVer, in)
} }
//PubKeyToAddr 公钥转为地址
func PubKeyToAddr(in []byte) string {
if value, ok := pubkeyCache.Get(string(in)); ok {
return value.(string)
}
addr := HashToAddress(NormalVer, in).String()
pubkeyCache.Add(string(in), addr)
return addr
}
//HashToAddress hash32 to address //HashToAddress hash32 to address
func HashToAddress(version byte, in []byte) *Address { func HashToAddress(version byte, in []byte) *Address {
a := new(Address) a := new(Address)
......
...@@ -105,21 +105,12 @@ func Sha3(b []byte) []byte { ...@@ -105,21 +105,12 @@ func Sha3(b []byte) []byte {
return data[:] return data[:]
} }
func sha2Hash(b []byte, out []byte) {
s := sha256.New()
s.Write(b[:])
tmp := s.Sum(nil)
s.Reset()
s.Write(tmp)
copy(out[:], s.Sum(nil))
}
// Sha2Sum Returns hash: SHA256( SHA256( data ) ) // Sha2Sum Returns hash: SHA256( SHA256( data ) )
// Where possible, using ShaHash() should be a bit faster // Where possible, using ShaHash() should be a bit faster
func Sha2Sum(b []byte) []byte { func Sha2Sum(b []byte) []byte {
out := make([]byte, 32) tmp := sha256.Sum256(b)
sha2Hash(b, out[:]) tmp = sha256.Sum256(tmp[:])
return out[:] return tmp[:]
} }
func rimpHash(in []byte, out []byte) { func rimpHash(in []byte, out []byte) {
......
...@@ -7,8 +7,9 @@ package merkle ...@@ -7,8 +7,9 @@ package merkle
import ( import (
"bytes" "bytes"
"crypto/sha256" "runtime"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
) )
...@@ -48,6 +49,120 @@ known ways of changing the transactions without affecting the merkle ...@@ -48,6 +49,120 @@ known ways of changing the transactions without affecting the merkle
root. root.
*/ */
/*GetMerkleRoot This implements a constant-space merkle root/path calculator, limited to 2^32 leaves. */
//flage =1 只计算roothash flage =2 只计算branch flage =3 计算roothash 和 branch
func getMerkleRoot(hashes [][]byte) []byte {
cache := make([]byte, 64)
level := 0
for len(hashes) > 1 {
if len(hashes)&1 != 0 { //奇数
hashes = append(hashes, hashes[len(hashes)-1])
}
index := 0
for i := 0; i < len(hashes); i += 2 {
hashes[index] = GetHashFromTwoHash(cache, hashes[i], hashes[i+1])
index++
}
level++
hashes = hashes[0:index]
}
if len(hashes) == 0 {
return nil
}
return hashes[0]
}
func log2(data int) int {
level := 1
if data <= 0 {
return 0
}
for {
data = data / 2
if data <= 1 {
return level
}
level++
}
}
func pow2(d int) (p int) {
if d <= 0 {
return 1
}
p = 1
for i := 0; i < d; i++ {
p *= 2
}
return p
}
func getMerkleRootPad(hashes [][]byte, step int) []byte {
level1 := log2(len(hashes))
level2 := log2(step)
root := getMerkleRoot(hashes)
cache := make([]byte, 64)
for i := 0; i < level2-level1; i++ {
root = GetHashFromTwoHash(cache, root, root)
}
return root
}
type childstate struct {
hash []byte
index int
}
//GetMerkleRoot 256构成一个组,进行计算
// n * step = hashes
// (hashes / n)
func GetMerkleRoot(hashes [][]byte) []byte {
ncpu := runtime.NumCPU()
if len(hashes) <= 80 || ncpu <= 1 {
return getMerkleRoot(hashes)
}
step := log2(len(hashes) / ncpu)
if step < 1 {
step = 1
}
step = pow2(step)
if step > 256 {
step = 256
}
ch := make(chan *childstate, 10)
//pad to step
rem := len(hashes) % step
l := len(hashes) / step
if rem != 0 {
l++
}
for i := 0; i < l; i++ {
end := (i + 1) * step
if end > len(hashes) {
end = len(hashes)
}
child := hashes[i*step : end]
go func(index int, h [][]byte) {
var subhash []byte
if len(h) != step {
subhash = getMerkleRootPad(h, step)
} else {
subhash = getMerkleRoot(h)
}
ch <- &childstate{
hash: subhash,
index: index,
}
}(i, child)
}
childlist := make([][]byte, l)
for i := 0; i < l; i++ {
sub := <-ch
childlist[sub.index] = sub.hash
}
return getMerkleRoot(childlist)
}
/*Computation This implements a constant-space merkle root/path calculator, limited to 2^32 leaves. */ /*Computation This implements a constant-space merkle root/path calculator, limited to 2^32 leaves. */
//flage =1 只计算roothash flage =2 只计算branch flage =3 计算roothash 和 branch //flage =1 只计算roothash flage =2 只计算branch flage =3 计算roothash 和 branch
func Computation(leaves [][]byte, flage int, branchpos uint32) (roothash []byte, mutated bool, pbranch [][]byte) { func Computation(leaves [][]byte, flage int, branchpos uint32) (roothash []byte, mutated bool, pbranch [][]byte) {
...@@ -66,6 +181,7 @@ func Computation(leaves [][]byte, flage int, branchpos uint32) (roothash []byte, ...@@ -66,6 +181,7 @@ func Computation(leaves [][]byte, flage int, branchpos uint32) (roothash []byte,
var matchlevel uint32 = 0xff var matchlevel uint32 = 0xff
mutated = false mutated = false
var matchh bool var matchh bool
cache := make([]byte, 64)
for count, h = range leaves { for count, h = range leaves {
if (uint32(count) == branchpos) && (flage&2) != 0 { if (uint32(count) == branchpos) && (flage&2) != 0 {
...@@ -89,7 +205,7 @@ func Computation(leaves [][]byte, flage int, branchpos uint32) (roothash []byte, ...@@ -89,7 +205,7 @@ func Computation(leaves [][]byte, flage int, branchpos uint32) (roothash []byte,
mutated = true mutated = true
} }
//计算inner[level] + h 的hash值 //计算inner[level] + h 的hash值
h = GetHashFromTwoHash(inner[level], h) h = GetHashFromTwoHash(cache, inner[level], h)
} }
inner[level] = h inner[level] = h
if matchh { if matchh {
...@@ -105,7 +221,7 @@ func Computation(leaves [][]byte, flage int, branchpos uint32) (roothash []byte, ...@@ -105,7 +221,7 @@ func Computation(leaves [][]byte, flage int, branchpos uint32) (roothash []byte,
if (flage&2) != 0 && matchh { if (flage&2) != 0 && matchh {
branch = append(branch, h) branch = append(branch, h)
} }
h = GetHashFromTwoHash(h, h) h = GetHashFromTwoHash(cache, h, h)
count += (1 << level) count += (1 << level)
level++ level++
// And propagate the result upwards accordingly. // And propagate the result upwards accordingly.
...@@ -118,7 +234,7 @@ func Computation(leaves [][]byte, flage int, branchpos uint32) (roothash []byte, ...@@ -118,7 +234,7 @@ func Computation(leaves [][]byte, flage int, branchpos uint32) (roothash []byte,
matchh = true matchh = true
} }
} }
h = GetHashFromTwoHash(inner[level], h) h = GetHashFromTwoHash(cache, inner[level], h)
level++ level++
} }
} }
...@@ -126,29 +242,13 @@ func Computation(leaves [][]byte, flage int, branchpos uint32) (roothash []byte, ...@@ -126,29 +242,13 @@ func Computation(leaves [][]byte, flage int, branchpos uint32) (roothash []byte,
} }
//GetHashFromTwoHash 计算左右节点hash的父hash //GetHashFromTwoHash 计算左右节点hash的父hash
func GetHashFromTwoHash(left []byte, right []byte) []byte { func GetHashFromTwoHash(parent []byte, left []byte, right []byte) []byte {
if left == nil || right == nil { if left == nil || right == nil {
return nil return nil
} }
leftlen := len(left)
rightlen := len(right)
parent := make([]byte, leftlen+rightlen)
copy(parent, left) copy(parent, left)
copy(parent[leftlen:], right) copy(parent[32:], right)
hash := sha256.Sum256(parent) return common.Sha2Sum(parent)
parenthash := sha256.Sum256(hash[:])
return parenthash[:]
}
//GetMerkleRoot 获取merkle roothash
func GetMerkleRoot(leaves [][]byte) (roothash []byte) {
if leaves == nil {
return nil
}
proothash, _, _ := Computation(leaves, 1, 0)
return proothash
} }
//GetMerkleBranch 获取指定txindex的branch position 从0开始 //GetMerkleBranch 获取指定txindex的branch position 从0开始
...@@ -160,11 +260,12 @@ func GetMerkleBranch(leaves [][]byte, position uint32) [][]byte { ...@@ -160,11 +260,12 @@ func GetMerkleBranch(leaves [][]byte, position uint32) [][]byte {
//GetMerkleRootFromBranch 通过branch 获取对应的roothash 用于指定txhash的proof证明 //GetMerkleRootFromBranch 通过branch 获取对应的roothash 用于指定txhash的proof证明
func GetMerkleRootFromBranch(merkleBranch [][]byte, leaf []byte, Index uint32) []byte { func GetMerkleRootFromBranch(merkleBranch [][]byte, leaf []byte, Index uint32) []byte {
hash := leaf hash := leaf
hashcache := make([]byte, 64)
for _, branch := range merkleBranch { for _, branch := range merkleBranch {
if (Index & 1) != 0 { if (Index & 1) != 0 {
hash = GetHashFromTwoHash(branch, hash) hash = GetHashFromTwoHash(hashcache, branch, hash)
} else { } else {
hash = GetHashFromTwoHash(hash, branch) hash = GetHashFromTwoHash(hashcache, hash, branch)
} }
Index >>= 1 Index >>= 1
} }
......
...@@ -6,7 +6,12 @@ package merkle ...@@ -6,7 +6,12 @@ package merkle
import ( import (
"bytes" "bytes"
"crypto/sha256"
"fmt"
"testing" "testing"
"github.com/33cn/chain33/common"
"github.com/stretchr/testify/assert"
) )
//测试两个交易的roothash以及branch.获取bitcoin的99997 block作为验证 //测试两个交易的roothash以及branch.获取bitcoin的99997 block作为验证
...@@ -248,3 +253,120 @@ func Test_SixTxMerkle(t *testing.T) { ...@@ -248,3 +253,120 @@ func Test_SixTxMerkle(t *testing.T) {
} }
} }
} }
func BenchmarkHashTwo(b *testing.B) {
b.ReportAllocs()
left := common.GetRandBytes(32, 32)
right := common.GetRandBytes(32, 32)
for i := 0; i < b.N; i++ {
getHashFromTwoHash(left, right)
}
}
func BenchmarkHashTwo2(b *testing.B) {
b.ReportAllocs()
left := common.GetRandBytes(32, 32)
right := common.GetRandBytes(32, 32)
cache := make([]byte, 64)
for i := 0; i < b.N; i++ {
GetHashFromTwoHash(cache, left, right)
}
}
//原来的版本更快,这个方案只是做一个性能测试的对比
func getHashFromTwoHash(left []byte, right []byte) []byte {
if left == nil || right == nil {
return nil
}
h := sha256.New()
h.Write(left)
h.Write(right)
hash1 := h.Sum(nil)
h.Reset()
h.Write(hash1)
return h.Sum(nil)
}
//优化办法:
//1. 减少内存分配
//2. 改进算法
var benchlen = 100000
func BenchmarkGetMerkelRoot(b *testing.B) {
b.ReportAllocs()
var hashlist [][]byte
for i := 0; i < benchlen; i++ {
key := common.GetRandBytes(32, 32)
hashlist = append(hashlist, key)
}
var prevroot []byte
for i := 0; i < b.N; i++ {
calc := make([][]byte, len(hashlist))
copy(calc, hashlist)
newroot := GetMerkleRoot(calc)
if prevroot != nil && !bytes.Equal(prevroot, newroot) {
b.Error("root is not the same")
}
prevroot = newroot
}
}
func BenchmarkGetMerkelRoot2(b *testing.B) {
b.ReportAllocs()
var hashlist [][]byte
for i := 0; i < benchlen; i++ {
key := common.GetRandBytes(32, 32)
hashlist = append(hashlist, key)
}
var prevroot []byte
for i := 0; i < b.N; i++ {
calc := make([][]byte, len(hashlist))
copy(calc, hashlist)
newroot, _, _ := Computation(calc, 1, 0)
if prevroot != nil && !bytes.Equal(prevroot, newroot) {
b.Error("root is not the same")
}
prevroot = newroot
}
}
var testlen = 14
func TestGetMerkelRoot1(t *testing.T) {
var hashlist [][]byte
for i := 0; i < testlen; i++ {
key := sha256.Sum256([]byte(fmt.Sprint(i)))
hashlist = append(hashlist, key[:])
}
hash1 := GetMerkleRoot(hashlist)
hashlist = nil
for i := 0; i < testlen; i++ {
key := sha256.Sum256([]byte(fmt.Sprint(i)))
hashlist = append(hashlist, key[:])
}
hash2 := getMerkleRoot(hashlist)
assert.Equal(t, hash1, hash2)
hashlist = nil
for i := 0; i < testlen; i++ {
key := sha256.Sum256([]byte(fmt.Sprint(i)))
hashlist = append(hashlist, key[:])
}
hash3, _, _ := Computation(hashlist, 1, 0)
assert.Equal(t, hash1, hash3)
}
func TestLog2(t *testing.T) {
assert.Equal(t, log2(0), 0)
assert.Equal(t, log2(1), 1)
assert.Equal(t, log2(2), 1)
assert.Equal(t, log2(3), 1)
assert.Equal(t, log2(4), 2)
assert.Equal(t, log2(5), 2)
assert.Equal(t, log2(6), 2)
assert.Equal(t, log2(7), 2)
assert.Equal(t, log2(8), 3)
assert.Equal(t, log2(256), 8)
}
...@@ -32,6 +32,7 @@ type executor struct { ...@@ -32,6 +32,7 @@ type executor struct {
gcli types.Chain33Client gcli types.Chain33Client
execapi api.ExecutorAPI execapi api.ExecutorAPI
receipts []*types.ReceiptData receipts []*types.ReceiptData
execCache map[string]drivers.Driver
} }
type executorCtx struct { type executorCtx struct {
...@@ -60,6 +61,7 @@ func newExecutor(ctx *executorCtx, exec *Executor, localdb dbm.KVDB, txs []*type ...@@ -60,6 +61,7 @@ func newExecutor(ctx *executorCtx, exec *Executor, localdb dbm.KVDB, txs []*type
receipts: receipts, receipts: receipts,
api: exec.qclient, api: exec.qclient,
gcli: exec.grpccli, gcli: exec.grpccli,
execCache: make(map[string]drivers.Driver),
} }
e.coinsAccount.SetDB(e.stateDB) e.coinsAccount.SetDB(e.stateDB)
return e return e
...@@ -103,17 +105,18 @@ func (e *executor) processFee(tx *types.Transaction) (*types.Receipt, error) { ...@@ -103,17 +105,18 @@ func (e *executor) processFee(tx *types.Transaction) (*types.Receipt, error) {
copyfrom := *accFrom copyfrom := *accFrom
accFrom.Balance = accFrom.GetBalance() - tx.Fee accFrom.Balance = accFrom.GetBalance() - tx.Fee
receiptBalance := &types.ReceiptAccountTransfer{Prev: &copyfrom, Current: accFrom} receiptBalance := &types.ReceiptAccountTransfer{Prev: &copyfrom, Current: accFrom}
e.coinsAccount.SaveAccount(accFrom) set := e.coinsAccount.GetKVSet(accFrom)
return e.cutFeeReceipt(accFrom, receiptBalance), nil e.coinsAccount.SaveKVSet(set)
return e.cutFeeReceipt(set, receiptBalance), nil
} }
return nil, types.ErrNoBalance return nil, types.ErrNoBalance
} }
func (e *executor) cutFeeReceipt(acc *types.Account, receiptBalance proto.Message) *types.Receipt { func (e *executor) cutFeeReceipt(kvset []*types.KeyValue, receiptBalance proto.Message) *types.Receipt {
feelog := &types.ReceiptLog{Ty: types.TyLogFee, Log: types.Encode(receiptBalance)} feelog := &types.ReceiptLog{Ty: types.TyLogFee, Log: types.Encode(receiptBalance)}
return &types.Receipt{ return &types.Receipt{
Ty: types.ExecPack, Ty: types.ExecPack,
KV: e.coinsAccount.GetKVSet(acc), KV: kvset,
Logs: append([]*types.ReceiptLog{}, feelog), Logs: append([]*types.ReceiptLog{}, feelog),
} }
} }
...@@ -190,7 +193,6 @@ func (e *executor) execCheckTx(tx *types.Transaction, index int) error { ...@@ -190,7 +193,6 @@ func (e *executor) execCheckTx(tx *types.Transaction, index int) error {
return types.ErrBalanceLessThanTenTimesFee return types.ErrBalanceLessThanTenTimesFee
} }
} }
e.setEnv(exec)
return exec.CheckTx(tx, index) return exec.CheckTx(tx, index)
} }
...@@ -219,8 +221,14 @@ func (e *executor) execDelLocal(tx *types.Transaction, r *types.ReceiptData, ind ...@@ -219,8 +221,14 @@ func (e *executor) execDelLocal(tx *types.Transaction, r *types.ReceiptData, ind
} }
func (e *executor) loadDriver(tx *types.Transaction, index int) (c drivers.Driver) { func (e *executor) loadDriver(tx *types.Transaction, index int) (c drivers.Driver) {
exec := drivers.LoadDriverAllow(tx, index, e.height) ename := string(tx.Execer)
exec, ok := e.execCache[ename]
if ok {
return exec
}
exec = drivers.LoadDriverAllow(tx, index, e.height)
e.setEnv(exec) e.setEnv(exec)
e.execCache[ename] = exec
return exec return exec
} }
...@@ -297,7 +305,6 @@ func (e *executor) execFee(tx *types.Transaction, index int) (*types.Receipt, er ...@@ -297,7 +305,6 @@ func (e *executor) execFee(tx *types.Transaction, index int) (*types.Receipt, er
feelog := &types.Receipt{Ty: types.ExecPack} feelog := &types.Receipt{Ty: types.ExecPack}
execer := string(tx.Execer) execer := string(tx.Execer)
ex := e.loadDriver(tx, index) ex := e.loadDriver(tx, index)
e.setEnv(ex)
//执行器名称 和 pubkey 相同,费用从内置的执行器中扣除,但是checkTx 中要过 //执行器名称 和 pubkey 相同,费用从内置的执行器中扣除,但是checkTx 中要过
//默认checkTx 中对这样的交易会返回 //默认checkTx 中对这样的交易会返回
if bytes.Equal(address.ExecPubkey(execer), tx.GetSignature().GetPubkey()) { if bytes.Equal(address.ExecPubkey(execer), tx.GetSignature().GetPubkey()) {
......
...@@ -264,6 +264,7 @@ func TestExecBlock(t *testing.T) { ...@@ -264,6 +264,7 @@ func TestExecBlock(t *testing.T) {
//区块执行新能测试 //区块执行新能测试
func BenchmarkExecBlock(b *testing.B) { func BenchmarkExecBlock(b *testing.B) {
b.ReportAllocs()
mock33 := newMockNode() mock33 := newMockNode()
defer mock33.Close() defer mock33.Close()
block := util.CreateCoinsBlock(mock33.GetGenesisKey(), 10000) block := util.CreateCoinsBlock(mock33.GetGenesisKey(), 10000)
......
...@@ -33,6 +33,7 @@ func Init(name string, sub []byte) { ...@@ -33,6 +33,7 @@ func Init(name string, sub []byte) {
} }
// the initialization process is relatively heavyweight, lots of reflact, so it's global // the initialization process is relatively heavyweight, lots of reflact, so it's global
func init() { func init() {
ety := types.LoadExecutorType(driverName) ety := types.LoadExecutorType(driverName)
ety.InitFuncList(types.ListMethod(&Coins{})) ety.InitFuncList(types.ListMethod(&Coins{}))
......
...@@ -42,8 +42,11 @@ func TestListType(t *testing.T) { ...@@ -42,8 +42,11 @@ func TestListType(t *testing.T) {
func BenchmarkGetActionValue(b *testing.B) { func BenchmarkGetActionValue(b *testing.B) {
action := &CoinsAction{Value: &CoinsAction_Transfer{Transfer: &types.AssetsTransfer{}}} action := &CoinsAction{Value: &CoinsAction_Transfer{Transfer: &types.AssetsTransfer{}}}
funclist := types.ListMethod(action) funclist := types.ListMethod(action)
b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, _, v := types.GetActionValue(action, funclist) action, ty, _ := types.GetActionValue(action, funclist)
assert.NotNil(b, v) if action != "Transfer" || ty != 0 {
b.Fatal(action)
}
} }
} }
...@@ -44,10 +44,13 @@ func init() { ...@@ -44,10 +44,13 @@ func init() {
} }
type subConfig struct { type subConfig struct {
EnableMavlPrefix bool `json:"enableMavlPrefix"` // 是否使能mavl加前缀
EnableMVCC bool `json:"enableMVCC"` EnableMavlPrefix bool `json:"enableMavlPrefix"`
EnableMavlPrune bool `json:"enableMavlPrune"` EnableMVCC bool `json:"enableMVCC"`
PruneHeight int32 `json:"pruneHeight"` // 是否使能mavl数据裁剪
EnableMavlPrune bool `json:"enableMavlPrune"`
// 裁剪高度间隔
PruneHeight int32 `json:"pruneHeight"`
} }
// New new mavl store module // New new mavl store module
......
This diff is collapsed.
...@@ -113,8 +113,9 @@ func getChainConfig(key string) (value interface{}, err error) { ...@@ -113,8 +113,9 @@ func getChainConfig(key string) (value interface{}, err error) {
// G 获取ChainConfig中的配置 // G 获取ChainConfig中的配置
func G(key string) (value interface{}, err error) { func G(key string) (value interface{}, err error) {
mu.Lock() mu.Lock()
defer mu.Unlock() value, err = getChainConfig(key)
return getChainConfig(key) mu.Unlock()
return
} }
// MG 获取mver config中的配置 // MG 获取mver config中的配置
...@@ -230,8 +231,8 @@ func S(key string, value interface{}) { ...@@ -230,8 +231,8 @@ func S(key string, value interface{}) {
//SetTitleOnlyForTest set title only for test use //SetTitleOnlyForTest set title only for test use
func SetTitleOnlyForTest(ti string) { func SetTitleOnlyForTest(ti string) {
mu.Lock() mu.Lock()
defer mu.Unlock()
title = ti title = ti
mu.Unlock()
} }
// Init 初始化 // Init 初始化
...@@ -289,8 +290,9 @@ func Init(t string, cfg *Config) { ...@@ -289,8 +290,9 @@ func Init(t string, cfg *Config) {
// GetTitle 获取title // GetTitle 获取title
func GetTitle() string { func GetTitle() string {
mu.Lock() mu.Lock()
defer mu.Unlock() s := title
return title mu.Unlock()
return s
} }
func isLocal() bool { func isLocal() bool {
...@@ -300,15 +302,16 @@ func isLocal() bool { ...@@ -300,15 +302,16 @@ func isLocal() bool {
// IsLocal 是否locak title // IsLocal 是否locak title
func IsLocal() bool { func IsLocal() bool {
mu.Lock() mu.Lock()
defer mu.Unlock() is := isLocal()
return isLocal() mu.Unlock()
return is
} }
// SetMinFee 设置最小费用 // SetMinFee 设置最小费用
func SetMinFee(fee int64) { func SetMinFee(fee int64) {
mu.Lock() mu.Lock()
defer mu.Unlock()
setMinFee(fee) setMinFee(fee)
mu.Unlock()
} }
func isPara() bool { func isPara() bool {
...@@ -318,8 +321,9 @@ func isPara() bool { ...@@ -318,8 +321,9 @@ func isPara() bool {
// IsPara 是否平行链 // IsPara 是否平行链
func IsPara() bool { func IsPara() bool {
mu.Lock() mu.Lock()
defer mu.Unlock() is := isPara()
return isPara() mu.Unlock()
return is
} }
// IsParaExecName 是否平行链执行器 // IsParaExecName 是否平行链执行器
...@@ -475,7 +479,6 @@ func InitCfg(path string) (*Config, *ConfigSubModule) { ...@@ -475,7 +479,6 @@ func InitCfg(path string) (*Config, *ConfigSubModule) {
func setFlatConfig(cfgstring string) { func setFlatConfig(cfgstring string) {
mu.Lock() mu.Lock()
defer mu.Unlock()
cfg := make(map[string]interface{}) cfg := make(map[string]interface{})
if _, err := tml.Decode(cfgstring, &cfg); err != nil { if _, err := tml.Decode(cfgstring, &cfg); err != nil {
panic(err) panic(err)
...@@ -484,6 +487,7 @@ func setFlatConfig(cfgstring string) { ...@@ -484,6 +487,7 @@ func setFlatConfig(cfgstring string) {
for k, v := range flat { for k, v := range flat {
setChainConfig("config."+k, v) setChainConfig("config."+k, v)
} }
mu.Unlock()
} }
func flatConfig(key string, conf map[string]interface{}, flat map[string]interface{}) { func flatConfig(key string, conf map[string]interface{}, flat map[string]interface{}) {
...@@ -506,8 +510,8 @@ func FlatConfig(conf map[string]interface{}) map[string]interface{} { ...@@ -506,8 +510,8 @@ func FlatConfig(conf map[string]interface{}) map[string]interface{} {
func setMver(title string, cfgstring string) { func setMver(title string, cfgstring string) {
mu.Lock() mu.Lock()
defer mu.Unlock()
mver[title] = newMversion(title, cfgstring) mver[title] = newMversion(title, cfgstring)
mu.Unlock()
} }
// InitCfgString 初始化配置 // InitCfgString 初始化配置
......
...@@ -95,7 +95,14 @@ func ListMethodByType(typ reflect.Type) map[string]reflect.Method { ...@@ -95,7 +95,14 @@ func ListMethodByType(typ reflect.Type) map[string]reflect.Method {
var nilValue = reflect.ValueOf(nil) var nilValue = reflect.ValueOf(nil)
// GetActionValue 获取执行器的action value // GetActionValue 获取执行器的action value
func GetActionValue(action interface{}, funclist map[string]reflect.Method) (string, int32, reflect.Value) { func GetActionValue(action interface{}, funclist map[string]reflect.Method) (vname string, vty int32, v reflect.Value) {
defer func() {
if e := recover(); e != nil {
vname = ""
vty = 0
v = nilValue
}
}()
var ty int32 var ty int32
if a, ok := action.(execTypeGet); ok { if a, ok := action.(execTypeGet); ok {
ty = a.GetTy() ty = a.GetTy()
...@@ -105,30 +112,19 @@ func GetActionValue(action interface{}, funclist map[string]reflect.Method) (str ...@@ -105,30 +112,19 @@ func GetActionValue(action interface{}, funclist map[string]reflect.Method) (str
return "", 0, nilValue return "", 0, nilValue
} }
rcvr := funclist["GetValue"].Func.Call([]reflect.Value{value}) rcvr := funclist["GetValue"].Func.Call([]reflect.Value{value})
if !IsOK(rcvr, 1) || IsNil(rcvr[0]) {
return "", 0, nilValue
}
if rcvr[0].Kind() != reflect.Ptr && rcvr[0].Kind() != reflect.Interface {
return "", 0, nilValue
}
elem := rcvr[0].Elem() elem := rcvr[0].Elem()
if IsNil(elem) {
return "", 0, nilValue
}
sname := elem.Type().String() sname := elem.Type().String()
datas := strings.Split(sname, "_") index := strings.LastIndex(sname, "_")
if len(datas) != 2 { if index == -1 || index == (len(sname)-1) {
return "", 0, nilValue return "", 0, nilValue
} }
funcname := "Get" + datas[1] tyname := sname[index+1:]
funcname := "Get" + tyname
if _, ok := funclist[funcname]; !ok { if _, ok := funclist[funcname]; !ok {
return "", 0, nilValue return "", 0, nilValue
} }
val := funclist[funcname].Func.Call([]reflect.Value{value}) val := funclist[funcname].Func.Call([]reflect.Value{value})
if !IsOK(val, 1) || IsNil(val[0]) { return tyname, ty, val[0]
return "", 0, nilValue
}
return datas[1], ty, val[0]
} }
// IsOK 是否存在 // IsOK 是否存在
......
...@@ -481,7 +481,7 @@ func (tx *Transaction) IsExpire(height, blocktime int64) bool { ...@@ -481,7 +481,7 @@ func (tx *Transaction) IsExpire(height, blocktime int64) bool {
//From 交易from地址 //From 交易from地址
func (tx *Transaction) From() string { func (tx *Transaction) From() string {
return address.PubKeyToAddress(tx.GetSignature().GetPubkey()).String() return address.PubKeyToAddr(tx.GetSignature().GetPubkey())
} }
//检查交易是否过期,过期返回true,未过期返回false //检查交易是否过期,过期返回true,未过期返回false
......
...@@ -192,19 +192,20 @@ func DelDupKey(kvs []*types.KeyValue) []*types.KeyValue { ...@@ -192,19 +192,20 @@ func DelDupKey(kvs []*types.KeyValue) []*types.KeyValue {
dupindex := make(map[string]int) dupindex := make(map[string]int)
hasdup := false hasdup := false
for i, kv := range kvs { for i, kv := range kvs {
if _, ok := dupindex[string(kv.Key)]; ok { skey := string(kv.Key)
if index, ok := dupindex[skey]; ok {
hasdup = true hasdup = true
kvs[index] = nil
} }
dupindex[string(kv.Key)] = i dupindex[skey] = i
} }
//没有重复的情况下,不需要重新处理 //没有重复的情况下,不需要重新处理
if !hasdup { if !hasdup {
return kvs return kvs
} }
index := 0 index := 0
for i, kv := range kvs { for _, kv := range kvs {
lastindex := dupindex[string(kv.Key)] if kv != nil {
if i == lastindex {
kvs[index] = kv kvs[index] = kv
index++ index++
} }
......
...@@ -290,6 +290,7 @@ func (mock *Chain33Mock) Close() { ...@@ -290,6 +290,7 @@ func (mock *Chain33Mock) Close() {
func (mock *Chain33Mock) closeNoLock() { func (mock *Chain33Mock) closeNoLock() {
mock.chain.Close() mock.chain.Close()
mock.store.Close()
mock.mem.Close() mock.mem.Close()
mock.cs.Close() mock.cs.Close()
mock.exec.Close() mock.exec.Close()
...@@ -297,7 +298,6 @@ func (mock *Chain33Mock) closeNoLock() { ...@@ -297,7 +298,6 @@ func (mock *Chain33Mock) closeNoLock() {
mock.network.Close() mock.network.Close()
mock.client.Close() mock.client.Close()
mock.rpc.Close() mock.rpc.Close()
mock.store.Close()
os.RemoveAll(mock.datadir) os.RemoveAll(mock.datadir)
} }
......
...@@ -7,6 +7,7 @@ package util ...@@ -7,6 +7,7 @@ package util
import ( import (
"testing" "testing"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/address" "github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/queue" "github.com/33cn/chain33/queue"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
...@@ -157,6 +158,26 @@ func TestDelDupKey(t *testing.T) { ...@@ -157,6 +158,26 @@ func TestDelDupKey(t *testing.T) {
assert.Equal(t, kvs, result) assert.Equal(t, kvs, result)
} }
func BenchmarkDelDupKey(b *testing.B) {
var kvs []*types.KeyValue
for i := 0; i < 1000; i++ {
key := common.GetRandBytes(20, 40)
value := common.GetRandBytes(40, 60)
kvs = append(kvs, &types.KeyValue{Key: key, Value: value})
if i%10 == 0 {
kvs = append(kvs, &types.KeyValue{Key: key, Value: value})
}
}
for i := 0; i < b.N; i++ {
testkv := make([]*types.KeyValue, len(kvs))
copy(testkv, kvs)
newkvs := DelDupKey(testkv)
if newkvs[len(newkvs)-1] == nil {
assert.NotNil(b, newkvs[len(newkvs)-1])
}
}
}
func TestDelDupTx(t *testing.T) { func TestDelDupTx(t *testing.T) {
txs := GenNoneTxs(TestPrivkeyList[0], 2) txs := GenNoneTxs(TestPrivkeyList[0], 2)
assert.Equal(t, 2, len(txs)) assert.Equal(t, 2, len(txs))
......
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