Commit 756e7aed authored by QM's avatar QM

Merge remote-tracking branch 'upstream/master' into bridgevmxgo_bsc_1201

parents e467beba 866292e2
......@@ -49,3 +49,4 @@ build/sendstock.toml
build/*.csv
build/CHANGELOG.md
plugin/dapp/dex/boss/build/
plugin/dapp/bridgevmxgo/cmd/build/addrTestConfig.toml
[fork.system]
ForkChainParamV1=110000
ForkChainParamV2=1692674
ForkCheckTxDup=75260
ForkBlockHash=209186
ForkMinerTime=350000
ForkTransferExec=408400
ForkExecKey=408400
ForkWithdraw=480000
ForkTxGroup=408400
ForkResetTx0=453400
ForkExecRollback=706531
ForkTxHeight=806578
ForkCheckBlockTime=1200000
ForkMultiSignAddress=1298600
ForkStateDBSet=1572391
ForkBlockCheck=1560000
ForkLocalDBAccess=1572391
ForkTxGroupPara=1687250
ForkBase58AddressCheck=1800000
# 这个fork只影响平行链,注册类似user.p.x.exec的driver,新开的平行链设为0即可,老的平行链要设置新的高度
ForkEnableParaRegExec=0
ForkCacheDriver=2580000
ForkTicketFundAddrV1=3350000
ForkRootHash=4500000
[fork.sub.coins]
Enable=0
[fork.sub.manage]
Enable=120000
ForkManageExec=400000
ForkManageAutonomyEnable=10000000
[fork.sub.accountmanager]
Enable=0
[fork.sub.autonomy]
Enable=7200000
ForkAutonomyDelRule=9500000
ForkAutonomyEnableItem=10000000
[fork.sub.blackwhite]
Enable=850000
ForkBlackWhiteV2=900000
[fork.sub.cert]
Enable=0
[fork.sub.coinsx]
Enable=0
[fork.sub.collateralize]
Enable=0
ForkCollateralizeTableUpdate=0
[fork.sub.dpos]
Enable=0
[fork.sub.echo]
Enable=0
[fork.sub.evm]
Enable=500000
# EVM合约中的数据分散存储,支持大数据量
ForkEVMState=650000
# EVM合约状态数据生成哈希,保存在主链的StateDB中
ForkEVMKVHash=1000000
# EVM合约支持ABI绑定和调用
ForkEVMABI=1250000
# EVM合约用户金额冻结
ForkEVMFrozen=1300000
# EEVM 黄皮v1分叉高度
ForkEVMYoloV1=9500000
# EVM合约支持交易组
ForkEVMTxGroup=0
[fork.sub.evmxgo]
Enable=0
[fork.sub.exchange]
Enable=0
[fork.sub.game]
Enable=0
[fork.sub.guess]
Enable=0
[fork.sub.hashlock]
Enable=0
ForkBadRepeatSecret=2715575
[fork.sub.issuance]
Enable=0
ForkIssuanceTableUpdate=0
[fork.sub.jsvm]
Enable=0
[fork.sub.lottery]
Enable=0
[fork.sub.mix]
Enable=0
[fork.sub.multisig]
Enable=0
[fork.sub.NormX]
Enable=0
[fork.sub.oracle]
Enable=0
[fork.sub.paracross]
Enable=1600000
ForkParacrossWithdrawFromParachain=1298600
ForkParacrossCommitTx=1850000
ForkLoopCheckCommitTxDone=3230000
ForkParaAssetTransferRbk=4500000
ForkParaSupervision=6000000
#以下仅平行链适用
ForkParaSelfConsStages=-1
ForkParaFullMinerHeight=-1
ForkParaRootHash=-1
[fork.sub.pokerbull]
Enable=0
[fork.sub.privacy]
Enable=980000
[fork.sub.qbftNode]
Enable=0
[fork.sub.relay]
Enable=570000
[fork.sub.retrieve]
Enable=0
ForkRetrive=180000
ForkRetriveAsset=3150000
[fork.sub.storage]
Enable=0
ForkStorageLocalDB=0
[fork.sub.ticket]
Enable=0
ForkTicketId=1062000
ForkTicketVrf=1770000
[fork.sub.token]
Enable=100899
ForkTokenBlackList=190000
ForkBadTokenSymbol=184000
ForkTokenPrice=560000
ForkTokenSymbolWithNumber=1298600
ForkTokenCheck=1600000
[fork.sub.trade]
Enable=100899
ForkTradeBuyLimit=301000
ForkTradeAsset=1010000
ForkTradeID=1450000
ForkTradeFixAssetDB=2500000
ForkTradePrice=3150000
[fork.sub.unfreeze]
Enable=0
ForkTerminatePart=1298600
ForkUnfreezeIDX=1450000
[fork.sub.valnode]
Enable=0
[fork.sub.vote]
Enable=0
[fork.sub.wasm]
Enable=0
[fork.sub.x2ethereum]
Enable=0
[fork.sub.store-kvmvccmavl]
ForkKvmvccmavl=1870000
......@@ -393,10 +393,12 @@ Enable=0
[fork.sub.issuance]
Enable=0
ForkIssuanceTableUpdate=0
ForkIssuancePrecision=0
[fork.sub.collateralize]
Enable=0
ForkCollateralizeTableUpdate=0
ForkCollateralizePrecision=0
#对已有的平行链如果不是从0开始同步数据,需要设置这个kvmvccmavl的对应平行链高度的fork,如果从0开始同步,statehash会跟以前mavl的不同
[fork.sub.store-kvmvccmavl]
......@@ -429,6 +431,7 @@ banks = ["1PTGVR7TUm1MJUH7M1UNcKBGMvfJ7nCrnN"]#Fee
#minFee最小手续费,配置时需*1e8(如:最小手续费收取1个,minFee=100000000)
coins = [
{ name = "bty", rate = 100000, minFee = 0 },
{ name = "coins.bty", rate = 100000, minFee = 0 },
{ name = "ETH", rate = 100000, minFee = 0 },
{ name = "USDT", rate = 100000, minFee = 0 },
]
......
......@@ -394,10 +394,12 @@ Enable=0
[fork.sub.issuance]
Enable=0
ForkIssuanceTableUpdate=0
ForkIssuancePrecision=0
[fork.sub.collateralize]
Enable=0
ForkCollateralizeTableUpdate=0
ForkCollateralizePrecision=0
#对已有的平行链如果不是从0开始同步数据,需要设置这个kvmvccmavl的对应平行链高度的fork,如果从0开始同步,statehash会跟以前mavl的不同
[fork.sub.store-kvmvccmavl]
......@@ -430,6 +432,7 @@ banks = ["1PTGVR7TUm1MJUH7M1UNcKBGMvfJ7nCrnN"]#Fee
#minFee最小手续费,配置时需*1e8(如:最小手续费收取1个,minFee=100000000)
coins = [
{ name = "bty", rate = 100000, minFee = 0 },
{ name = "coins.bty", rate = 100000, minFee = 0 },
{ name = "ETH", rate = 100000, minFee = 0 },
{ name = "USDT", rate = 100000, minFee = 0 },
]
......
......@@ -95,6 +95,8 @@ maxConnectNum=100
disableFindLANPeers=false
# 配置为全节点模式,全节点保存所有分片数据
isFullNode=false
# 分片数据默认保存比例,最低可配置为10
percentage=30
[rpc]
jrpcBindAddr="localhost:8801"
......@@ -214,13 +216,16 @@ enableMemVal=true
tkCloseCacheLen=100000
[store.sub.kvmvccmavl]
# 开启该配置可以方便遍历最新的状态数据,节省磁盘空间可以关闭该配置项
enableMVCCIter=true
enableMavlPrefix=false
enableMVCC=false
enableMavlPrune=false
pruneMavlHeight=10000
# 开启该配置项会精简mvcc历史高度的数据,默认不精简
enableMVCCPrune=false
pruneMVCCHeight=10000
# 每次精简mvcc的间隔高度,默认每100w高度精简一次
pruneMVCCHeight=1000000
# 是否使能mavl数据载入内存
enableMemTree=true
# 是否使能mavl叶子节点数据载入内存
......@@ -248,6 +253,12 @@ rescanMultisigAddr=false
enableStat=false
enableMVCC=false
alias=["token1:token","token2:token","token3:token"]
# 记录地址相关的交易列表,便于按地址查询交易
disableAddrIndex=false
# 记录每个高度总的手续费消耗量
disableFeeIndex=false
# 开启后会进一步精简localdb,用户查询合约功能会受影响,纯挖矿节点可以开启节省磁盘空间
disableExecLocal=false
[exec.sub.token]
saveTokenTxList=true
......@@ -336,6 +347,7 @@ banks = ["1PTGVR7TUm1MJUH7M1UNcKBGMvfJ7nCrnN"]#Fee
#minFee最小手续费,配置时需*1e8(如:最小手续费收取1个,minFee=100000000)
coins = [
{ name = "bty", rate = 100000, minFee = 0 },
{ name = "coins.bty", rate = 100000, minFee = 0 },
{ name = "ETH", rate = 100000, minFee = 0 },
{ name = "USDT", rate = 100000, minFee = 0 },
]
\ No newline at end of file
......@@ -3,7 +3,7 @@ module github.com/33cn/plugin
go 1.15
require (
github.com/33cn/chain33 v1.65.6-0.20211118074307-04e724cee41c
github.com/33cn/chain33 v1.65.6-0.20211130044919-77e92a34438a
github.com/BurntSushi/toml v0.3.1
github.com/NebulousLabs/Sia v1.3.7
github.com/NebulousLabs/errors v0.0.0-20181203160057-9f787ce8f69e // indirect
......@@ -33,6 +33,7 @@ require (
github.com/pkg/errors v0.9.1
github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d
github.com/rs/cors v1.7.0
github.com/shopspring/decimal v1.2.0
github.com/spf13/cobra v1.1.1
github.com/stretchr/testify v1.7.0
github.com/tjfoc/gmsm v1.3.2
......@@ -44,4 +45,5 @@ require (
google.golang.org/protobuf v1.27.1
gopkg.in/sourcemap.v1 v1.0.5 // indirect
gopkg.in/yaml.v2 v2.4.0
gotest.tools v2.2.0+incompatible
)
......@@ -48,10 +48,8 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/33cn/chain33 v1.65.6-0.20211025083411-82c4406c6701 h1:XrlmULs3WrRHCJm/isW5WCiH3WlfeFgZHWDY0ZarVTI=
github.com/33cn/chain33 v1.65.6-0.20211025083411-82c4406c6701/go.mod h1:27Z1b54wJ6EhE1IGA3S5AxSQ/t8dktFVgPnkLNbMFoE=
github.com/33cn/chain33 v1.65.6-0.20211118074307-04e724cee41c h1:XLvYVstAXMuDpVHNAzW/7jV3e/LlTa+z8i7zLLiwK0E=
github.com/33cn/chain33 v1.65.6-0.20211118074307-04e724cee41c/go.mod h1:27Z1b54wJ6EhE1IGA3S5AxSQ/t8dktFVgPnkLNbMFoE=
github.com/33cn/chain33 v1.65.6-0.20211130044919-77e92a34438a h1:jLm8iWEWpWk0+dQZK7cQUFOxUhACsJ1heDc5Pme+drc=
github.com/33cn/chain33 v1.65.6-0.20211130044919-77e92a34438a/go.mod h1:27Z1b54wJ6EhE1IGA3S5AxSQ/t8dktFVgPnkLNbMFoE=
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M=
......@@ -2244,6 +2242,7 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
......
......@@ -834,7 +834,7 @@ func (cs *ConsensusState) createProposalBlock() (block *ttypes.QbftBlock) {
// Mempool validated transactions
beg := time.Now()
pblock := cs.client.BuildBlock()
pblock := cs.client.BuildBlock(cs.Height - 1)
if pblock == nil {
qbftlog.Error("createProposalBlock BuildBlock fail")
return nil
......@@ -1252,7 +1252,9 @@ func (cs *ConsensusState) finalizeCommit(height int64) {
// commit block
commitBlock := cs.ProposalBlock.Data
cs.client.CommitBlock(commitBlock)
if !DetachExec() {
cs.client.CommitBlock(commitBlock.Clone())
}
if bytes.Equal(cs.privValidator.GetAddress(), block.QbftBlock.Header.ProposerAddr) {
qbftlog.Info(fmt.Sprintf("Proposer reach consensus. Current: %v/%v/%v", cs.Height, cs.Round, cs.Step),
"CommitRound", cs.CommitRound, "tx-len", len(commitBlock.Txs), "cost", types.Since(cs.begCons),
......@@ -1264,10 +1266,7 @@ func (cs *ConsensusState) finalizeCommit(height int64) {
"proposer-addr", fmt.Sprintf("%X", ttypes.Fingerprint(block.QbftBlock.Header.ProposerAddr)),
"seq", block.Header.Sequence)
}
reqblock, err := cs.client.RequestBlock(height)
if err != nil {
panic(fmt.Sprintf("finalizeCommit RequestBlock fail: %v", err))
}
reqblock := cs.client.WaitBlock(height)
stateCopy.LastResultsHash = reqblock.Hash(cs.client.GetAPI().GetConfig())
//check whether need update validator nodes
......@@ -1428,6 +1427,11 @@ func (cs *ConsensusState) addProposalBlock(proposalBlock *tmtypes.QbftBlock) (er
qbftlog.Info(fmt.Sprintf("Consensus set proposal block. Current: %v/%v/%v", cs.Height, cs.Round, cs.Step),
"ProposalBlockHash", fmt.Sprintf("%X", cs.ProposalBlockHash), "cost", types.Since(cs.begCons))
if DetachExec() {
qbftlog.Info("write proposal block in advance")
go cs.client.CommitBlock(cs.ProposalBlock.Data.Clone())
}
// Update Valid* if we can.
prevotes := cs.Votes.Prevotes(cs.Round)
blockID, hasTwoThirds := prevotes.TwoThirdsMajority()
......
......@@ -215,7 +215,7 @@ func validateBlock(stateDB *CSStateDB, s State, b *ttypes.QbftBlock) error {
// validate prev block info
if !bytes.Equal(b.Header.LastBlockID.Hash, s.LastBlockID.Hash) {
return fmt.Errorf("Wrong Block.Header.LastBlockID. Expected %v, got %v", s.LastBlockID, b.Header.LastBlockID)
return fmt.Errorf("Wrong Block.Header.LastBlockID. Expected %X, got %X", s.LastBlockID.Hash, b.Header.LastBlockID.Hash)
}
newTxs := b.Header.NumTxs
......@@ -225,16 +225,16 @@ func validateBlock(stateDB *CSStateDB, s State, b *ttypes.QbftBlock) error {
// validate app info
if !bytes.Equal(b.Header.AppHash, s.AppHash) {
return fmt.Errorf("Wrong Block.Header.AppHash. Expected %X, got %v", s.AppHash, b.Header.AppHash)
return fmt.Errorf("Wrong Block.Header.AppHash. Expected %X, got %X", s.AppHash, b.Header.AppHash)
}
if !bytes.Equal(b.Header.ConsensusHash, s.ConsensusParams.Hash()) {
return fmt.Errorf("Wrong Block.Header.ConsensusHash. Expected %X, got %v", s.ConsensusParams.Hash(), b.Header.ConsensusHash)
return fmt.Errorf("Wrong Block.Header.ConsensusHash. Expected %X, got %X", s.ConsensusParams.Hash(), b.Header.ConsensusHash)
}
if !bytes.Equal(b.Header.LastResultsHash, s.LastResultsHash) {
return fmt.Errorf("Wrong Block.Header.LastResultsHash. Expected %X, got %v", s.LastResultsHash, b.Header.LastResultsHash)
return fmt.Errorf("Wrong Block.Header.LastResultsHash. Expected %X, got %X", s.LastResultsHash, b.Header.LastResultsHash)
}
if !bytes.Equal(b.Header.ValidatorsHash, s.Validators.Hash()) {
return fmt.Errorf("Wrong Block.Header.ValidatorsHash. Expected %X, got %v", s.Validators.Hash(), b.Header.ValidatorsHash)
return fmt.Errorf("Wrong Block.Header.ValidatorsHash. Expected %X, got %X", s.Validators.Hash(), b.Header.ValidatorsHash)
}
// Validate block LastCommit.
......
......@@ -482,37 +482,47 @@ func (pc *peerConn) stopForError(r interface{}) {
}
}
// 数据压缩后发送, 内部对相关数组进行重复利用
func encodeMsg(msg types.Message, pbuf *[]byte, typeID byte) []byte {
buf := *pbuf
buf = buf[:cap(buf)]
// 数据压缩
func encodeMsg(msg types.Message, typeID byte) []byte {
raw := types.Encode(msg)
buf = snappy.Encode(buf, raw)
cmp := byte(0)
if len(raw) > MaxMsgPacketPayloadSize {
qbftlog.Info("packet exceed max size", "old", len(raw), "new", len(buf))
}
*pbuf = buf
// 复用raw数组作为压缩数据返回, 需要比较容量是否够大
if cap(raw) >= len(buf)+5 {
raw = raw[:len(buf)+5]
} else {
raw = make([]byte, len(buf)+5)
buf := make([]byte, 0)
buf = snappy.Encode(buf, raw)
cmp = byte(1)
qbftlog.Info("compress large message", "old", len(raw), "new", len(buf))
raw = buf
}
raw[0] = typeID
ebuf := make([]byte, len(raw)+6)
ebuf[0] = typeID
ebuf[1] = cmp
bytelen := make([]byte, 4)
binary.BigEndian.PutUint32(bytelen, uint32(len(buf)))
copy(raw[1:5], bytelen)
copy(raw[5:], buf)
return raw
binary.BigEndian.PutUint32(bytelen, uint32(len(raw)))
copy(ebuf[2:6], bytelen)
copy(ebuf[6:], raw)
return ebuf
}
func (pc *peerConn) sendRoutine() {
// 数据解压
func decodeMsg(msg []byte, cmp byte) ([]byte, error) {
if cmp == byte(0) {
return msg, nil
}
buf := make([]byte, 0)
buf, err := snappy.Decode(buf, msg)
if err != nil {
return nil, err
}
qbftlog.Info("uncompress large message", "old", len(msg), "new", len(buf))
return buf, nil
}
func (pc *peerConn) sendRoutine() {
FOR_LOOP:
for {
select {
case msg := <-pc.sendQueue:
raw := encodeMsg(msg.Msg, &buf, msg.TypeID)
raw := encodeMsg(msg.Msg, msg.TypeID)
_, err := pc.bufWriter.Write(raw)
if err != nil {
qbftlog.Error("peerConn sendroutine write data failed", "error", err)
......@@ -533,40 +543,41 @@ FOR_LOOP:
func (pc *peerConn) recvRoutine() {
FOR_LOOP:
for {
//typeID+msgLen+msg
var buf [5]byte
//typeID+cmp+msgLen+msg
var buf [6]byte
_, err := io.ReadFull(pc.bufReader, buf[:])
if err != nil {
qbftlog.Error("Connection failed @ recvRoutine (reading byte)", "conn", pc, "err", err)
qbftlog.Error("recvRoutine read byte fail", "conn", pc, "err", err)
pc.stopForError(err)
break FOR_LOOP
}
pkt := msgPacket{}
pkt.TypeID = buf[0]
len := binary.BigEndian.Uint32(buf[1:])
if len > 0 {
buf2 := make([]byte, len)
cmp := buf[1]
msgLen := binary.BigEndian.Uint32(buf[2:6])
if msgLen <= 0 {
qbftlog.Error("recvRoutine read invalid data", "msgLen", msgLen, "cmp", cmp, "peerIP", pc.ip.String())
continue
}
buf2 := make([]byte, msgLen)
_, err = io.ReadFull(pc.bufReader, buf2)
if err != nil {
qbftlog.Error("recvRoutine read data fail", "conn", pc, "err", err)
pc.stopForError(err)
qbftlog.Error("recvRoutine read data fail", "err", err, "peerIP", pc.ip.String())
continue
}
buf3 := make([]byte, len)
buf3, err = snappy.Decode(buf3, buf2)
buf3, err := decodeMsg(buf2, cmp)
if err != nil {
qbftlog.Error("recvRoutine snappy decode fail", "conn", pc, "err", err)
pc.stopForError(err)
qbftlog.Error("recvRoutine decode msg fail", "err", err, "peerIP", pc.ip.String())
continue
}
pkt.Bytes = buf3
}
if v, ok := ttypes.MsgMap[pkt.TypeID]; ok {
realMsg := reflect.New(v).Interface()
err := proto.Unmarshal(pkt.Bytes, realMsg.(proto.Message))
if err != nil {
qbftlog.Error("peerConn recvRoutine Unmarshal data failed", "err", err)
qbftlog.Error("recvRoutine Unmarshal data fail", "msgTy", pkt.TypeID, "msgLen", len(pkt.Bytes), "err", err, "peerIP", pc.ip.String())
continue
}
if pc.transferChannel != nil && (pkt.TypeID == ttypes.ProposalID || pkt.TypeID == ttypes.VoteID ||
......@@ -595,12 +606,8 @@ FOR_LOOP:
pc.updateStateQueue <- MsgInfo{pkt.TypeID, realMsg.(proto.Message), pc.ID(), pc.ip.String()}
}
} else {
err := fmt.Errorf("Unknown message type %v", pkt.TypeID)
qbftlog.Error("Connection failed @ recvRoutine", "conn", pc, "err", err)
pc.stopForError(err)
break FOR_LOOP
qbftlog.Error("receive unknown message type", "type", pkt.TypeID, "peerIP", pc.ip.String())
}
}
pc.quitUpdate <- struct{}{}
pc.quitBeat <- struct{}{}
......
......@@ -59,6 +59,7 @@ var (
useAggSig atomic.Value // false
multiBlocks atomic.Value // 1
gossipVotes atomic.Value
detachExec atomic.Value // false
zeroHash [32]byte
random *rand.Rand
......@@ -112,6 +113,7 @@ type subConfig struct {
UseAggregateSignature bool `json:"useAggregateSignature"`
MultiBlocks int64 `json:"multiBlocks"`
MessageInterval int32 `json:"messageInterval"`
DetachExecution bool `json:"detachExecution"`
}
func applyConfig(cfg *types.Consensus, sub []byte) {
......@@ -166,6 +168,7 @@ func applyConfig(cfg *types.Consensus, sub []byte) {
if subcfg.MessageInterval > 0 {
peerGossipSleepDuration.Store(subcfg.MessageInterval)
}
detachExec.Store(subcfg.DetachExecution)
gossipVotes.Store(true)
}
......@@ -175,6 +178,11 @@ func UseAggSig() bool {
return useAggSig.Load().(bool)
}
// DetachExec returns whether detach Execution from Consensus
func DetachExec() bool {
return detachExec.Load().(bool)
}
// DefaultDBProvider returns a database
func DefaultDBProvider(name string) dbm.DB {
return dbm.NewDB(name, "leveldb", dbPath, 0)
......@@ -230,7 +238,7 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
}
qbftlog.Info("show qbft info", "version", qbftVersion, "sign", ttypes.CryptoName, "useAggSig", UseAggSig(),
"genesisFile", genesisFile, "privFile", privFile)
"detachExec", DetachExec(), "genesisFile", genesisFile, "privFile", privFile)
ttypes.InitMessageMap()
......@@ -526,12 +534,8 @@ func (client *Client) CheckTxDup(txs []*types.Transaction, height int64) (transa
}
// BuildBlock build a new block
func (client *Client) BuildBlock() *types.Block {
lastBlock, err := client.RequestLastBlock()
if err != nil {
qbftlog.Error("BuildBlock fail", "err", err)
return nil
}
func (client *Client) BuildBlock(height int64) *types.Block {
lastBlock := client.WaitBlock(height)
cfg := client.GetAPI().GetConfig()
txs := client.RequestTx(int(cfg.GetP(lastBlock.Height+1).MaxTxNumber)-1, nil)
// placeholder
......@@ -561,7 +565,7 @@ func (client *Client) CommitBlock(block *types.Block) {
}
// WaitBlock by height
func (client *Client) WaitBlock(height int64) bool {
func (client *Client) WaitBlock(height int64) *types.Block {
ticker := time.NewTicker(10 * time.Second)
defer ticker.Stop()
......@@ -570,13 +574,16 @@ func (client *Client) WaitBlock(height int64) bool {
select {
case <-client.ctx.Done():
qbftlog.Info("WaitBlock quit")
return false
return nil
case <-ticker.C:
qbftlog.Info("Still waiting block......", "height", height, "cost", time.Since(beg))
default:
newHeight, err := client.getLastHeight()
if err == nil && newHeight >= height {
return true
block, err := client.RequestBlock(height)
if err == nil {
return block
}
}
time.Sleep(50 * time.Millisecond)
}
......
......@@ -60,11 +60,11 @@ func main() {
}
Perf(argsWithoutProg[1], argsWithoutProg[2], argsWithoutProg[3], argsWithoutProg[4], argsWithoutProg[5])
case "perfV2":
if len(argsWithoutProg) != 4 {
if len(argsWithoutProg) != 5 {
fmt.Print(errors.New("参数错误").Error())
return
}
PerfV2(argsWithoutProg[1], argsWithoutProg[2], argsWithoutProg[3])
PerfV2(argsWithoutProg[1], argsWithoutProg[2], argsWithoutProg[3], argsWithoutProg[4])
case "put":
if len(argsWithoutProg) != 3 {
fmt.Print(errors.New("参数错误").Error())
......@@ -96,7 +96,7 @@ func main() {
func LoadHelp() {
fmt.Println("Available Commands:")
fmt.Println("perf [host, size, num, interval, duration] : 写数据性能测试,interval单位为100毫秒,host形式为ip:port")
fmt.Println("perfV2 [host, size, duration] : 写数据性能测试,host形式为ip:port")
fmt.Println("perfV2 [host, size, interval, duration] : 写数据性能测试,interval单位为秒,host形式为ip:port")
fmt.Println("put [ip, size] : 写数据")
fmt.Println("get [ip, hash] : 读数据")
fmt.Println("valnode [ip, pubkey, power] : 增加/删除/修改tendermint节点")
......@@ -232,16 +232,17 @@ func Perf(host, txsize, num, sleepinterval, totalduration string) {
}
// PerfV2
func PerfV2(host, txsize, duration string) {
func PerfV2(host, txsize, sleepinterval, duration string) {
durInt, _ := strconv.Atoi(duration)
sizeInt, _ := strconv.Atoi(txsize)
sleep, _ := strconv.Atoi(sleepinterval)
numCPU := runtime.NumCPU()
numThread := numCPU * 2
numSend := numCPU * 3
numThread := numCPU
numSend := numCPU * 2
ch := make(chan struct{}, numThread)
chSend := make(chan struct{}, numSend)
numInt := 10000
batchNum := 200
batchNum := 100
txChan := make(chan *types.Transaction, numInt)
var blockHeight int64
total := int64(0)
......@@ -307,24 +308,42 @@ func PerfV2(host, txsize, duration string) {
defer conn.Close()
gcli := types.NewChain33Client(conn)
txs := &types.Transactions{Txs: make([]*types.Transaction, 0, batchNum)}
retryTxs := make([]*types.Transaction, 0, batchNum*2)
for tx := range txChan {
txs.Txs = append(txs.Txs, tx)
if len(txs.Txs) == batchNum {
_, err := gcli.SendTransactions(context.Background(), txs)
atomic.AddInt64(&total, int64(batchNum))
txs.Txs = txs.Txs[:0]
if len(retryTxs) > 0 {
txs.Txs = append(txs.Txs, retryTxs...)
retryTxs = retryTxs[:0]
}
if len(txs.Txs) >= batchNum {
reps, err := gcli.SendTransactions(context.Background(), txs)
if err != nil {
if strings.Contains(err.Error(), "ErrChannelClosed") {
log.Error("sendtxs", "err", err)
return
}
log.Error("sendtx", "err", err.Error())
time.Sleep(time.Second)
atomic.AddInt64(&total, int64(len(txs.Txs)))
// retry failed txs
for index, reply := range reps.GetReplyList() {
if reply.IsOk {
continue
}
atomic.AddInt64(&success, int64(batchNum))
if string(reply.GetMsg()) == types.ErrChannelClosed.Error() {
return
}
if string(reply.GetMsg()) == types.ErrMemFull.Error() ||
string(reply.GetMsg()) == types.ErrManyTx.Error() {
retryTxs = append(retryTxs, txs.Txs[index])
}
}
atomic.AddInt64(&success, int64(len(txs.Txs)-len(retryTxs)))
if len(retryTxs) > 0 {
time.Sleep(time.Second * time.Duration(sleep))
}
txs.Txs = txs.Txs[:0]
}
}
chSend <- struct{}{}
}()
......
......@@ -29,8 +29,8 @@ func init() {
//InitFork ...
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork(AutonomyX, "Enable", 0)
cfg.RegisterDappFork(AutonomyX, ForkAutonomyDelRule, 9500000)
cfg.RegisterDappFork(AutonomyX, ForkAutonomyEnableItem, 10000000)
cfg.RegisterDappFork(AutonomyX, ForkAutonomyDelRule, 0)
cfg.RegisterDappFork(AutonomyX, ForkAutonomyEnableItem, 0)
}
//InitExecutor ...
......
......@@ -30,8 +30,8 @@ func init() {
//InitFork ...
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork(BlackwhiteX, "ForkBlackWhiteV2", 900000)
cfg.RegisterDappFork(BlackwhiteX, "Enable", 850000)
cfg.RegisterDappFork(BlackwhiteX, "ForkBlackWhiteV2", 0)
cfg.RegisterDappFork(BlackwhiteX, "Enable", 0)
}
//InitExecutor ...
......
......@@ -5,8 +5,8 @@ services:
build:
context: .
dockerfile: Dockerfile-bridgevmxgo
ports:
- "9901:9901"
#ports:
# - "9901:9901"
ebrelayerb:
build:
......@@ -29,9 +29,9 @@ services:
PARAFILE: "/root/chain33.para33.toml"
expose:
- "8802"
ports:
- "8801:8801"
- "8901:8901"
#ports:
# - "8801:8801"
# - "8901:8901"
chain32:
entrypoint: /root/entrypoint.sh
......
......@@ -1020,6 +1020,45 @@ function Testethereum2EVMToChain33_usdt() {
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function Testethereum2EVMToChain33_usdt() {
# 查询 ETH 这端 bridgeBank 地址原来是
result=$(${CLIA} ethereum balance -o "${ethBridgeBank}" -t "${ethereumUSDTERC20TokenAddr}")
# cli_ret "${result}" "balance" ".balance" "0"
# ETH 这端 lock 12个
result=$(${CLIA} ethereum lock -m 12 -k "${ethTestAddrKey1}" -r "${chain33ReceiverAddr}" -t "${ethereumUSDTERC20TokenAddr}")
cli_ret "${result}" "lock"
# eth 等待 2 个区块
sleep 4
# 查询 ETH 这端 bridgeBank 地址 12
result=$(${CLIA} ethereum balance -o "${ethBridgeBank}" -t "${ethereumUSDTERC20TokenAddr}")
# cli_ret "${result}" "balance" ".balance" "12"
sleep ${maturityDegree}
# chain33 chain33EthBridgeTokenAddr(ETH合约中)查询 lock 金额
result=$(${Chain33Cli} evm query -a "${chain33USDTBridgeTokenAddr}" -c "${chain33TestAddr1}" -b "balanceOf(${chain33ReceiverAddr})")
# 结果是 7 * le8
# is_equal "${result}" "700000000"
updateConfig "USDT" "${chain33USDTBridgeTokenAddr}"
configbridgevmxgoAddr "${XgoChain33BridgeBank}"
${EvmxgoBoss4xCLI} chain33 offline approve_erc20 -a 330000000000 -s "${XgoChain33BridgeBank}" -c "${chain33USDTBridgeTokenAddr}" -k "${chain33ReceiverAddrKey}" -f 1 --chainID "${chain33ID}"
chain33_offline_send_evm "approve_erc20.txt"
hash=$(${Chain33Cli} send evm call -f 1 -k "${chain33ReceiverAddr}" -e "${XgoChain33BridgeBank}" -p "lock(${chain33TestAddr2}, ${chain33USDTBridgeTokenAddr}, 500000000)" --chainID "${chain33ID}")
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} evm query -a "${chain33USDTBridgeTokenAddr}" -c "${chain33DeployAddr}" -b "balanceOf(${chain33ReceiverAddr})")
# is_equal "${result}" "4200000000"
result=$(${Chain33Cli} evm query -a "${chain33USDTBridgeTokenAddr}" -c "${chain33DeployAddr}" -b "balanceOf(${XgoChain33BridgeBank})")
# is_equal "${result}" "500000000"
}
function AllRelayerMainTest() {
set +e
......
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
set -x
set +e
# 只测试 lock 操作,不测试 burn
source "./publicTest.sh"
source "./relayerPublic.sh"
# ETH 部署合约者的私钥 用于部署合约时签名使用
ethDeployAddr="0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a"
ethDeployKey="8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230"
# chain33 部署合约者的私钥 用于部署合约时签名使用
chain33DeployAddr="1N6HstkyLFS8QCeVfdvYxx1xoryXoJtvvZ"
Chain33Cli="../../chain33-cli"
chain33BridgeBank=""
ethBridgeBank=""
chain33BtyERC20TokenAddr="1111111111111111111114oLvT2"
ethereumBycERC20TokenAddr=""
multisignChain33Addr=""
multisignEthAddr=""
ethereumYccBridgeTokenAddr=""
chain33YccERC20TokenAddr=""
CLIA="./ebcli_A"
chain33ID=0
function set_offline_token_Bty() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
echo -e "${GRE}===== chain33 端 configLockedTokenOfflineSave BTY ======${NOC}"
# echo '2:#配置自动转离线钱包(bty, 1000, 50%)'
hash=$(${Chain33Cli} send evm call -f 1 -k "${chain33DeployAddr}" -e "${chain33BridgeBank}" -p "configLockedTokenOfflineSave(${chain33BtyERC20TokenAddr},BTY,100000000000,50)" --khainID "${chain33ID}")
check_tx "${Chain33Cli}" "${hash}"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function lock_multisign_Bty_test() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
lock_bty_multisign 330 "330.0000" "0.0000"
lock_bty_multisign 800 "565.0000" "565.0000"
lock_bty_multisign 500 "532.5000" "1097.5000"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function transfer_multisign_Bty_test() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# transfer test
# shellcheck disable=SC2154
hash=$(${CLIA} chain33 multisign transfer -a 100 -r "${chain33BridgeBank}" -k "${chain33MultisignKeyA},${chain33MultisignKeyB},${chain33MultisignKeyC},${chain33MultisignKeyD}" | jq -r ".msg")
check_tx "${Chain33Cli}" "${hash}"
sleep 2
result=$(${Chain33Cli} account balance -a "${multisignChain33Addr}" -e evm)
balance_ret "${result}" "997.5000"
result=$(${Chain33Cli} account balance -a "${chain33BridgeBank}" -e evm)
balance_ret "${result}" "632.5000"
# shellcheck disable=SC2154
hash=$(${CLIA} chain33 multisign transfer -a 100 -r "${chain33MultisignA}" -k "${chain33MultisignKeyA},${chain33MultisignKeyB},${chain33MultisignKeyC},${chain33MultisignKeyD}" | jq -r ".msg")
check_tx "${Chain33Cli}" "${hash}"
sleep 2
result=$(${Chain33Cli} account balance -a "${multisignChain33Addr}" -e evm)
balance_ret "${result}" "897.5000"
result=$(${Chain33Cli} account balance -a "${chain33MultisignA}" -e evm)
balance_ret "${result}" "100.0000"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function lockBty() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
set_offline_token_Bty
lock_multisign_Bty_test
transfer_multisign_Bty_test
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function set_offline_token_Chain33Ycc() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
echo -e "${GRE}===== chain33 端 configLockedTokenOfflineSave ERC20 YCC ======${NOC}"
# echo '2:#配置自动转离线钱包(YCC, 100, 60%)'
hash=$(${Chain33Cli} send evm call -f 1 -k "${chain33DeployAddr}" -e "${chain33BridgeBank}" -p "configLockedTokenOfflineSave(${chain33YccERC20TokenAddr},YCC,10000000000,60)" --chainID "${chain33ID}")
check_tx "${Chain33Cli}" "${hash}"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function lock_multisign_Chain33Ycc_test() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
lock_chain33_ycc_multisign 30 30 0
lock_chain33_ycc_multisign 70 40 60
lock_chain33_ycc_multisign 260 120 240
lock_chain33_ycc_multisign 10 52 318
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function transfer_multisign_Chain33Ycc_test() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# transfer test
hash=$(${CLIA} chain33 multisign transfer -a 10 -r "${chain33BridgeBank}" -t "${chain33YccERC20TokenAddr}" -k "${chain33MultisignKeyA},${chain33MultisignKeyB},${chain33MultisignKeyC},${chain33MultisignKeyD}" | jq -r ".msg")
check_tx "${Chain33Cli}" "${hash}"
sleep 2
result=$(${Chain33Cli} evm query -a "${chain33YccERC20TokenAddr}" -c "${chain33BridgeBank}" -b "balanceOf(${chain33BridgeBank})")
is_equal "${result}" "6200000000"
result=$(${Chain33Cli} evm query -a "${chain33YccERC20TokenAddr}" -c "${multisignChain33Addr}" -b "balanceOf(${multisignChain33Addr})")
is_equal "${result}" "30800000000"
hash=$(${CLIA} chain33 multisign transfer -a 5 -r "${chain33MultisignA}" -t "${chain33YccERC20TokenAddr}" -k "${chain33MultisignKeyA},${chain33MultisignKeyB},${chain33MultisignKeyC},${chain33MultisignKeyD}" | jq -r ".msg")
check_tx "${Chain33Cli}" "${hash}"
sleep 2
result=$(${Chain33Cli} evm query -a "${chain33YccERC20TokenAddr}" -c "${chain33MultisignA}" -b "balanceOf(${chain33MultisignA})")
is_equal "${result}" "500000000"
result=$(${Chain33Cli} evm query -a "${chain33YccERC20TokenAddr}" -c "${multisignChain33Addr}" -b "balanceOf(${multisignChain33Addr})")
is_equal "${result}" "30300000000"
# 判断 ETH 这端是否金额一致
result=$(${CLIA} ethereum balance -o "${ethDeployAddr}" -t "${ethereumYccBridgeTokenAddr}")
cli_ret "${result}" "balance" ".balance" "370"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function lockChain33Ycc() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
set_offline_token_Chain33Ycc
lock_multisign_Chain33Ycc_test
transfer_multisign_Chain33Ycc_test
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function set_offline_token_Eth() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# echo '2:#配置自动转离线钱包(eth, 20, 50%)'
result=$(${CLIA} ethereum multisign set_offline_token -s ETH -m 20)
cli_ret "${result}" "set_offline_token -s ETH -m 20"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function lock_multisign_Eth_test() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
result=$(${CLIA} ethereum balance -o "${ethBridgeBank}")
cli_ret "${result}" "balance" ".balance" "0"
result=$(${CLIA} ethereum balance -o "${multisignEthAddr}")
cli_ret "${result}" "balance" ".balance" "0"
lock_eth_multisign 19 19 0
lock_eth_multisign 1 10 10
lock_eth_multisign 16 13 23
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function transfer_multisign_Eth_test() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# transfer
# shellcheck disable=SC2154
${CLIA} ethereum multisign transfer -a 3 -r "${ethBridgeBank}" -k "${ethMultisignKeyA},${ethMultisignKeyB},${ethMultisignKeyC},${ethMultisignKeyD}"
sleep 2
result=$(${CLIA} ethereum balance -o "${ethBridgeBank}")
cli_ret "${result}" "balance" ".balance" "16"
result=$(${CLIA} ethereum balance -o "${multisignEthAddr}")
cli_ret "${result}" "balance" ".balance" "20"
# transfer
# shellcheck disable=SC2154
${CLIA} ethereum multisign transfer -a 5 -r "${ethMultisignA}" -k "${ethMultisignKeyA},${ethMultisignKeyB},${ethMultisignKeyC},${ethMultisignKeyD}"
sleep 2
result=$(${CLIA} ethereum balance -o "${ethMultisignA}")
cli_ret "${result}" "balance" ".balance" "105"
result=$(${CLIA} ethereum balance -o "${multisignEthAddr}")
cli_ret "${result}" "balance" ".balance" "15"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function lockEth() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
echo -e "${GRE}===== ethereum 端 lock multisign ETH ======${NOC}"
set_offline_token_Eth
lock_multisign_Eth_test
transfer_multisign_Eth_test
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function set_offline_token_EthYcc() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# echo '2:#配置自动转离线钱包(ycc, 100, 40%)'
result=$(${CLIA} ethereum multisign set_offline_token -s BYC -m 100 -p 40 -t "${ethereumBycERC20TokenAddr}")
cli_ret "${result}" "set_offline_token -s BYC -m 100"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function lock_multisign_EthYcc() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
result=$(${CLIA} ethereum balance -o "${ethBridgeBank}" -t "${ethereumBycERC20TokenAddr}")
cli_ret "${result}" "balance" ".balance" "0"
result=$(${CLIA} ethereum balance -o "${multisignEthAddr}" -t "${ethereumBycERC20TokenAddr}")
cli_ret "${result}" "balance" ".balance" "0"
lock_ethereum_ycc_multisign 70 70 0
lock_ethereum_ycc_multisign 30 60 40
lock_ethereum_ycc_multisign 60 72 88
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function transfer_multisign_EthYcc() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# transfer
# multisignEthAddr 要有手续费
${CLIA} ethereum transfer -k "${ethDeployKey}" -m 10 -r "${multisignEthAddr}"
sleep 2
# transfer
${CLIA} ethereum multisign transfer -a 8 -r "${ethBridgeBank}" -t "${ethereumBycERC20TokenAddr}" -k "${ethMultisignKeyA},${ethMultisignKeyB},${ethMultisignKeyC},${ethMultisignKeyD}"
sleep 2
result=$(${CLIA} ethereum balance -o "${ethBridgeBank}" -t "${ethereumBycERC20TokenAddr}")
cli_ret "${result}" "balance" ".balance" "80"
result=$(${CLIA} ethereum balance -o "${multisignEthAddr}" -t "${ethereumBycERC20TokenAddr}")
cli_ret "${result}" "balance" ".balance" "80"
# transfer
${CLIA} ethereum multisign transfer -a 10 -r "${ethMultisignA}" -t "${ethereumBycERC20TokenAddr}" -k "${ethMultisignKeyA},${ethMultisignKeyB},${ethMultisignKeyC},${ethMultisignKeyD}"
sleep 2
result=$(${CLIA} ethereum balance -o "${ethMultisignA}" -t "${ethereumBycERC20TokenAddr}")
cli_ret "${result}" "balance" ".balance" "10"
result=$(${CLIA} ethereum balance -o "${multisignEthAddr}" -t "${ethereumBycERC20TokenAddr}")
cli_ret "${result}" "balance" ".balance" "70"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function lockEthYcc() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
echo -e "${GRE}===== ethereum 端 lock multisign YCC ======${NOC}"
set_offline_token_EthYcc
lock_multisign_EthYcc
transfer_multisign_EthYcc
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
......@@ -5,7 +5,10 @@
package executor
import (
"math"
"github.com/33cn/chain33/common/db/table"
"github.com/shopspring/decimal"
"github.com/33cn/chain33/account"
"github.com/33cn/chain33/common"
......@@ -569,12 +572,25 @@ func (action *Action) CollateralizeBorrow(borrow *pty.CollateralizeBorrow) (*typ
return nil, err
}
// 精度转换 #1024
// token精度转成精度8
valueReal := borrow.GetValue()
cfg := action.Collateralize.GetAPI().GetConfig()
if cfg.IsDappFork(action.Collateralize.GetHeight(), pty.CollateralizeX, pty.ForkCollateralizePrecision) {
precisionNum := int(math.Log10(float64(cfg.GetTokenPrecision())))
valueReal = decimal.NewFromInt(valueReal).Shift(int32(-precisionNum)).Shift(8).IntPart()
}
// 根据价格和需要借贷的金额,计算需要质押的抵押物数量
btyFrozen, err := getBtyNumToFrozen(borrow.GetValue(), lastPrice, coll.LiquidationRatio)
btyFrozen, err := getBtyNumToFrozen(valueReal, lastPrice, coll.LiquidationRatio)
if err != nil {
clog.Error("CollateralizeBorrow.getBtyNumToFrozen", "CollID", coll.CollateralizeId, "addr", action.fromaddr, "execaddr", action.execaddr, "error", err)
return nil, err
}
// bty精度8转成coins精度
if cfg.IsDappFork(action.Collateralize.GetHeight(), pty.CollateralizeX, pty.ForkCollateralizePrecision) {
precisionNum := int(math.Log10(float64(cfg.GetCoinPrecision())))
btyFrozen = decimal.NewFromInt(btyFrozen).Shift(-8).Shift(int32(precisionNum)).IntPart()
}
// 检查抵押物账户余额
if !action.CheckExecAccountBalance(action.fromaddr, btyFrozen, 0) {
......@@ -680,8 +696,22 @@ func (action *Action) CollateralizeRepay(repay *pty.CollateralizeRepay) (*types.
return nil, pty.ErrRecordNotExist
}
// 精度转换 #1024
// token精度转成精度8
cfg := action.Collateralize.GetAPI().GetConfig()
valueReal := borrowRecord.DebtValue
if cfg.IsDappFork(action.Collateralize.GetHeight(), pty.CollateralizeX, pty.ForkCollateralizePrecision) {
precisionNum := int(math.Log10(float64(cfg.GetTokenPrecision())))
valueReal = decimal.NewFromInt(valueReal).Shift(int32(-precisionNum)).Shift(8).IntPart()
}
// 借贷金额+利息
fee := ((borrowRecord.DebtValue * coll.StabilityFeeRatio) / 1e8) * 1e4
fee := ((valueReal * coll.StabilityFeeRatio) / 1e8) * 1e4
// 精度8转成token精度
if cfg.IsDappFork(action.Collateralize.GetHeight(), pty.CollateralizeX, pty.ForkCollateralizePrecision) {
precisionNum := int(math.Log10(float64(cfg.GetTokenPrecision())))
fee = decimal.NewFromInt(fee).Shift(-8).Shift(int32(precisionNum)).IntPart()
}
realRepay := borrowRecord.DebtValue + fee
// 检查
......@@ -813,7 +843,17 @@ func (action *Action) CollateralizeAppend(cAppend *pty.CollateralizeAppend) (*ty
// 构造借出记录
borrowRecord.CollateralValue += cAppend.CollateralValue
borrowRecord.CollateralPrice = lastPrice
borrowRecord.LiquidationPrice = calcLiquidationPrice(borrowRecord.DebtValue, borrowRecord.CollateralValue)
// 精度转换 #1024
cfg := action.Collateralize.GetAPI().GetConfig()
debtValueReal := borrowRecord.DebtValue
collateralValueReal := borrowRecord.CollateralValue
if cfg.IsDappFork(action.Collateralize.GetHeight(), pty.CollateralizeX, pty.ForkCollateralizePrecision) {
precisionNum := int(math.Log10(float64(cfg.GetTokenPrecision())))
debtValueReal = decimal.NewFromInt(debtValueReal).Shift(int32(-precisionNum)).Shift(8).IntPart()
collateralValueReal = decimal.NewFromInt(collateralValueReal).Shift(int32(-precisionNum)).Shift(8).IntPart()
}
borrowRecord.LiquidationPrice = calcLiquidationPrice(debtValueReal, collateralValueReal)
if borrowRecord.LiquidationPrice*PriceWarningRate < lastPrice {
// 告警解除
if borrowRecord.Status == pty.CollateralizeUserStatusWarning {
......
......@@ -30,6 +30,7 @@ func init() {
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork(CollateralizeX, "Enable", 0)
cfg.RegisterDappFork(CollateralizeX, ForkCollateralizeTableUpdate, 0)
cfg.RegisterDappFork(CollateralizeX, ForkCollateralizePrecision, 0)
}
//InitExecutor ...
......@@ -157,7 +158,7 @@ func CreateRawCollateralizeCreateTx(cfg *types.Chain33Config, parm *Collateraliz
llog.Error("CreateRawCollateralizeCreateTx", "parm", parm)
return nil, types.ErrInvalidParam
}
totalBalanceInt64, err := types.FormatFloatDisplay2Value(parm.TotalBalance, cfg.GetCoinPrecision())
totalBalanceInt64, err := types.FormatFloatDisplay2Value(parm.TotalBalance, cfg.GetTokenPrecision())
if err != nil {
return nil, errors.Wrapf(types.ErrInvalidParam, "FormatFloatDisplay2Value.TotalBalance")
}
......@@ -188,7 +189,7 @@ func CreateRawCollateralizeBorrowTx(cfg *types.Chain33Config, parm *Collateraliz
llog.Error("CreateRawCollateralizeBorrowTx", "parm", parm)
return nil, types.ErrInvalidParam
}
valueInt64, err := types.FormatFloatDisplay2Value(parm.Value, cfg.GetCoinPrecision())
valueInt64, err := types.FormatFloatDisplay2Value(parm.Value, cfg.GetTokenPrecision())
if err != nil {
return nil, errors.Wrapf(types.ErrInvalidParam, "FormatFloatDisplay2Value.Value")
}
......@@ -315,7 +316,7 @@ func CreateRawCollateralizeRetrieveTx(cfg *types.Chain33Config, parm *Collateral
llog.Error("CreateRawCollateralizeCloseTx", "parm", parm)
return nil, types.ErrInvalidParam
}
balanceInt64, err := types.FormatFloatDisplay2Value(parm.Balance, cfg.GetCoinPrecision())
balanceInt64, err := types.FormatFloatDisplay2Value(parm.Balance, cfg.GetTokenPrecision())
if err != nil {
return nil, errors.Wrapf(types.ErrInvalidParam, "FormatFloatDisplay2Value.Balance")
}
......@@ -348,11 +349,11 @@ func CreateRawCollateralizeManageTx(cfg *types.Chain33Config, parm *Collateraliz
llog.Error("CreateRawCollateralizeManageTx", "parm", parm)
return nil, types.ErrInvalidParam
}
totalBalanceInt64, err := types.FormatFloatDisplay2Value(parm.TotalBalance, cfg.GetCoinPrecision())
totalBalanceInt64, err := types.FormatFloatDisplay2Value(parm.TotalBalance, cfg.GetTokenPrecision())
if err != nil {
return nil, errors.Wrapf(types.ErrInvalidParam, "FormatFloatDisplay2Value.totalBalance")
}
debtCeilingInt64, err := types.FormatFloatDisplay2Value(parm.DebtCeiling, cfg.GetCoinPrecision())
debtCeilingInt64, err := types.FormatFloatDisplay2Value(parm.DebtCeiling, cfg.GetTokenPrecision())
if err != nil {
return nil, errors.Wrapf(types.ErrInvalidParam, "FormatFloatDisplay2Value.DebtCeiling")
}
......
......@@ -56,4 +56,5 @@ const (
//fork ...
var (
ForkCollateralizeTableUpdate = "ForkCollateralizeTableUpdate"
ForkCollateralizePrecision = "ForkCollateralizePrecision"
)
......@@ -29,17 +29,17 @@ func init() {
//InitFork ...
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork(ExecutorName, EVMEnable, 500000)
cfg.RegisterDappFork(ExecutorName, EVMEnable, 0)
// EVM合约中的数据分散存储,支持大数据量
cfg.RegisterDappFork(ExecutorName, ForkEVMState, 650000)
cfg.RegisterDappFork(ExecutorName, ForkEVMState, 0)
// EVM合约状态数据生成哈希,保存在主链的StateDB中
cfg.RegisterDappFork(ExecutorName, ForkEVMKVHash, 1000000)
cfg.RegisterDappFork(ExecutorName, ForkEVMKVHash, 0)
// EVM合约支持ABI绑定和调用
cfg.RegisterDappFork(ExecutorName, ForkEVMABI, 1250000)
cfg.RegisterDappFork(ExecutorName, ForkEVMABI, 0)
// EEVM合约用户金额冻结
cfg.RegisterDappFork(ExecutorName, ForkEVMFrozen, 1300000)
cfg.RegisterDappFork(ExecutorName, ForkEVMFrozen, 0)
// EEVM 黄皮v1分叉高度
cfg.RegisterDappFork(ExecutorName, ForkEVMYoloV1, 9500000)
cfg.RegisterDappFork(ExecutorName, ForkEVMYoloV1, 0)
// EVM合约支持交易组
cfg.RegisterDappFork(ExecutorName, ForkEVMTxGroup, 0)
}
......
......@@ -260,13 +260,7 @@ func (action *evmxgoAction) mint(mint *evmxgotypes.EvmxgoMint, tx2lock *types.Tr
return nil, err
}
// TODO check()
evmxgodb, err := loadEvmxgoDB(action.db, mint.GetSymbol())
if err != nil {
if err != evmxgotypes.ErrEvmxgoSymbolNotExist {
return nil, err
}
// evmxgo合约,只要配置了就可以铸币
// evmxgo合约,配置symbol对应的实际地址,检验地址正确才能发币
configSymbol, err := loadEvmxgoMintConfig(action.db, mint.GetSymbol())
if err != nil || configSymbol == nil {
elog.Error("evmxgo mint ", "not config symbol", mint.GetSymbol(), "error", err)
......@@ -278,6 +272,12 @@ func (action *evmxgoAction) mint(mint *evmxgotypes.EvmxgoMint, tx2lock *types.Tr
return nil, evmxgotypes.ErrNotCorrectBridgeTokenAddress
}
evmxgodb, err := loadEvmxgoDB(action.db, mint.GetSymbol())
if err != nil {
if err != evmxgotypes.ErrEvmxgoSymbolNotExist {
return nil, err
}
evmxgodb = newEvmxgoDB(mint)
}
......
......@@ -564,14 +564,9 @@ func (a *Action) matchModel(leftAccountDB, rightAccountDB *account.DB, payload *
return logs, kvs, nil
}
//根据订单号查询,分为两步,优先去localdb中查询,如没有则再去状态数据库中查询
// 1.挂单中得订单信会根据orderID在localdb中存储
// 2.订单撤销,或者成交后,根据orderID在localdb中存储得数据会被删除,这时只能到状态数据库中查询
//根据订单号去状态数据库中查询
// 1.localdb删除顺序,先实时删除缓存,区块生成时统一修改db。会导致缓存数据被删除但查询时缓存查询不到会去db查询依旧可以查询到删除的数据
func findOrderByOrderID(statedb dbm.KV, localdb dbm.KV, orderID int64) (*et.Order, error) {
table := NewMarketOrderTable(localdb)
primaryKey := []byte(fmt.Sprintf("%022d", orderID))
row, err := table.GetData(primaryKey)
if err != nil {
data, err := statedb.Get(calcOrderKey(orderID))
if err != nil {
elog.Error("findOrderByOrderID.Get", "orderID", orderID, "err", err.Error())
......@@ -585,10 +580,6 @@ func findOrderByOrderID(statedb dbm.KV, localdb dbm.KV, orderID int64) (*et.Orde
}
order.Executed = order.GetLimitOrder().Amount - order.Balance
return &order, nil
}
order := row.Data.(*et.Order)
order.Executed = order.GetLimitOrder().Amount - order.Balance
return order, nil
}
func findOrderIDListByPrice(localdb dbm.KV, left, right *et.Asset, price int64, op, direction int32, primaryKey string) (*et.OrderList, error) {
......
package executor
import (
"fmt"
"github.com/33cn/chain33/common/db/table"
"github.com/33cn/chain33/types"
ety "github.com/33cn/plugin/plugin/dapp/exchange/types"
......@@ -191,10 +193,10 @@ func (e *exchange) updateOrder(marketTable, orderTable, historyTable *table.Tabl
}
}
//删除原有状态orderID
order.Status = ety.Ordered
err = orderTable.DelRow(order)
primaryKey := []byte(fmt.Sprintf("%022d", order.OrderID))
err = orderTable.Del(primaryKey)
if err != nil {
elog.Error("updateIndex", "orderTable.DelRow", err.Error())
elog.Error("updateIndex", "orderTable.Del", err.Error())
return err
}
order.Status = ety.Revoked
......
......@@ -273,16 +273,5 @@ coins = [
{name = "CCNY", rate = 100000, minFee = 0},
]
#[mver.exec.sub.exchange.ForkParamV1]
#banks = [
# "1PTGVR7TUm1MJUH7M1UNcKBGMvfJ7nCrnN"
#]
#coins = [
# {name = "bty", rate = 100000, minFee = 1000000},
# {name = "CCNY", rate = 100000, minFee = 1000000},
#]
[fork.sub.exchange]
Enable=0
\ No newline at end of file
#ForkParamV1=1
\ No newline at end of file
......@@ -26,7 +26,7 @@ func init() {
//InitFork ...
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork(HashlockX, "Enable", 0)
cfg.RegisterDappFork(HashlockX, ForkBadRepeatSecretX, 2715575)
cfg.RegisterDappFork(HashlockX, ForkBadRepeatSecretX, 0)
}
//InitExecutor ...
......
......@@ -5,6 +5,8 @@
package executor
import (
"math"
"github.com/33cn/chain33/account"
"github.com/33cn/chain33/common"
dbm "github.com/33cn/chain33/common/db"
......@@ -13,6 +15,7 @@ import (
"github.com/33cn/chain33/types"
pty "github.com/33cn/plugin/plugin/dapp/issuance/types"
tokenE "github.com/33cn/plugin/plugin/dapp/token/executor"
"github.com/shopspring/decimal"
)
// List control
......@@ -536,12 +539,25 @@ func (action *Action) IssuanceDebt(debt *pty.IssuanceDebt) (*types.Receipt, erro
return nil, err
}
// 精度转换 #1024
// 先将token由token精度转成精度8
valueReal := debt.GetValue()
cfg := action.Issuance.GetAPI().GetConfig()
if cfg.IsDappFork(action.Issuance.GetHeight(), pty.IssuanceX, pty.ForkIssuancePrecision) {
precisionNum := int(math.Log10(float64(cfg.GetTokenPrecision())))
valueReal = decimal.NewFromInt(valueReal).Shift(int32(-precisionNum)).Shift(8).IntPart()
}
// 根据价格和需要借贷的金额,计算需要质押的抵押物数量
btyFrozen, err := getBtyNumToFrozen(debt.Value, lastPrice, issu.LiquidationRatio)
btyFrozen, err := getBtyNumToFrozen(valueReal, lastPrice, issu.LiquidationRatio)
if err != nil {
clog.Error("IssuanceDebt.getBtyNumToFrozen", "CollID", issu.IssuanceId, "addr", action.fromaddr, "execaddr", action.execaddr, "error", err)
return nil, err
}
// 再将bty由精度8转成coins精度
if cfg.IsDappFork(action.Issuance.GetHeight(), pty.IssuanceX, pty.ForkIssuancePrecision) {
precisionNum := int(math.Log10(float64(cfg.GetCoinPrecision())))
btyFrozen = decimal.NewFromInt(btyFrozen).Shift(-8).Shift(int32(precisionNum)).IntPart()
}
// 检查抵押物账户余额
if !action.CheckExecAccountBalance(action.fromaddr, btyFrozen, 0) {
......
......@@ -30,6 +30,7 @@ func init() {
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork(IssuanceX, "Enable", 0)
cfg.RegisterDappFork(IssuanceX, ForkIssuanceTableUpdate, 0)
cfg.RegisterDappFork(IssuanceX, ForkIssuancePrecision, 0)
}
//InitExecutor ...
......@@ -148,11 +149,11 @@ func CreateRawIssuanceCreateTx(cfg *types.Chain33Config, parm *IssuanceCreateTx)
return nil, types.ErrInvalidParam
}
totalBalanceInt64, err := types.FormatFloatDisplay2Value(parm.TotalBalance, cfg.GetCoinPrecision())
totalBalanceInt64, err := types.FormatFloatDisplay2Value(parm.TotalBalance, cfg.GetTokenPrecision())
if err != nil {
return nil, errors.Wrapf(types.ErrInvalidParam, "FormatFloatDisplay2Value.totalBalance")
}
debtCeilingInt64, err := types.FormatFloatDisplay2Value(parm.DebtCeiling, cfg.GetCoinPrecision())
debtCeilingInt64, err := types.FormatFloatDisplay2Value(parm.DebtCeiling, cfg.GetTokenPrecision())
if err != nil {
return nil, errors.Wrapf(types.ErrInvalidParam, "FormatFloatDisplay2Value.DebtCeiling")
}
......@@ -187,7 +188,7 @@ func CreateRawIssuanceDebtTx(cfg *types.Chain33Config, parm *IssuanceDebtTx) (*t
llog.Error("CreateRawIssuanceBorrowTx", "parm", parm)
return nil, types.ErrInvalidParam
}
valueInt64, err := types.FormatFloatDisplay2Value(parm.Value, cfg.GetCoinPrecision())
valueInt64, err := types.FormatFloatDisplay2Value(parm.Value, cfg.GetTokenPrecision())
if err != nil {
return nil, errors.Wrapf(types.ErrInvalidParam, "FormatFloatDisplay2Value.Value")
}
......
......@@ -55,4 +55,5 @@ const (
//fork ...
var (
ForkIssuanceTableUpdate = "ForkIssuanceTableUpdate"
ForkIssuancePrecision = "ForkIssuancePrecision"
)
......@@ -47,7 +47,7 @@ func newAction(t *Paracross, tx *types.Transaction) *action {
func getNodes(db dbm.KV, key []byte) (map[string]struct{}, []string, error) {
item, err := db.Get(key)
if err != nil {
clog.Info("getNodes", "get db key", string(key), "failed", err)
//clog.Info("getNodes", "get db key", string(key), "failed", err)
if isNotFound(err) {
err = pt.ErrTitleNotExist
}
......@@ -836,7 +836,7 @@ func isHaveCrossTxs(cfg *types.Chain33Config, status *pt.ParacrossNodeStatus) bo
func (a *action) procCrossTxs(status *pt.ParacrossNodeStatus) (*types.Receipt, error) {
cfg := a.api.GetConfig()
if enableParacrossTransfer && status.Height > 0 && isHaveCrossTxs(cfg, status) {
clog.Debug("paracross.Commit commitDone do cross", "height", status.Height)
clog.Info("paracross.Commit commitDone do cross", "height", status.Height)
crossTxReceipt, err := a.execCrossTxs(status)
if err != nil {
return nil, err
......@@ -1021,25 +1021,25 @@ func (a *action) isAllowConsensJump(commit *pt.ParacrossNodeStatus, titleStatus
return a.isAllowMainConsensJump(commit, titleStatus), nil
}
func execCrossTx(a *action, cross *types.TransactionDetail, crossTxHash []byte) (*types.Receipt, error) {
if !bytes.HasSuffix(cross.Tx.Execer, []byte(pt.ParaX)) {
func execCrossTxNew(a *action, cross *types.Transaction, crossTxHash []byte) (*types.Receipt, error) {
if !bytes.HasSuffix(cross.Execer, []byte(pt.ParaX)) {
return nil, nil
}
var payload pt.ParacrossAction
err := types.Decode(cross.Tx.Payload, &payload)
err := types.Decode(cross.Payload, &payload)
if err != nil {
clog.Crit("paracross.Commit Decode Tx failed", "error", err, "txHash", common.ToHex(crossTxHash))
return nil, err
}
if payload.Ty == pt.ParacrossActionCrossAssetTransfer {
act, err := getCrossAction(payload.GetCrossAssetTransfer(), string(cross.Tx.Execer))
act, err := getCrossAction(payload.GetCrossAssetTransfer(), string(cross.Execer))
if err != nil {
clog.Crit("paracross.Commit getCrossAction Tx failed", "error", err, "txHash", common.ToHex(crossTxHash))
return nil, err
}
if act == pt.ParacrossMainAssetWithdraw || act == pt.ParacrossParaAssetTransfer {
receipt, err := a.crossAssetTransfer(payload.GetCrossAssetTransfer(), act, cross.Tx)
receipt, err := a.crossAssetTransfer(payload.GetCrossAssetTransfer(), act, cross)
if err != nil {
clog.Crit("paracross.Commit crossAssetTransfer Tx failed", "error", err, "act", act, "txHash", common.ToHex(crossTxHash))
return nil, err
......@@ -1052,7 +1052,7 @@ func execCrossTx(a *action, cross *types.TransactionDetail, crossTxHash []byte)
//主链共识后,执行主链资产withdraw, 在支持CrossAssetTransfer之前使用此action
if payload.Ty == pt.ParacrossActionAssetWithdraw {
receiptWithdraw, err := a.assetWithdraw(payload.GetAssetWithdraw(), cross.Tx)
receiptWithdraw, err := a.assetWithdraw(payload.GetAssetWithdraw(), cross)
if err != nil {
clog.Crit("paracross.Commit withdraw Tx failed", "error", err, "txHash", common.ToHex(crossTxHash))
return nil, errors.Cause(err)
......@@ -1064,26 +1064,69 @@ func execCrossTx(a *action, cross *types.TransactionDetail, crossTxHash []byte)
return nil, nil
}
func rollbackCrossTx(a *action, cross *types.TransactionDetail, crossTxHash []byte) (*types.Receipt, error) {
if !bytes.HasSuffix(cross.Tx.Execer, []byte(pt.ParaX)) {
//func execCrossTx(a *action, cross *types.TransactionDetail, crossTxHash []byte) (*types.Receipt, error) {
// if !bytes.HasSuffix(cross.Tx.Execer, []byte(pt.ParaX)) {
// return nil, nil
// }
// var payload pt.ParacrossAction
// err := types.Decode(cross.Tx.Payload, &payload)
// if err != nil {
// clog.Crit("paracross.Commit Decode Tx failed", "error", err, "txHash", common.ToHex(crossTxHash))
// return nil, err
// }
//
// if payload.Ty == pt.ParacrossActionCrossAssetTransfer {
// act, err := getCrossAction(payload.GetCrossAssetTransfer(), string(cross.Tx.Execer))
// if err != nil {
// clog.Crit("paracross.Commit getCrossAction Tx failed", "error", err, "txHash", common.ToHex(crossTxHash))
// return nil, err
// }
// if act == pt.ParacrossMainAssetWithdraw || act == pt.ParacrossParaAssetTransfer {
// receipt, err := a.crossAssetTransfer(payload.GetCrossAssetTransfer(), act, cross.Tx)
// if err != nil {
// clog.Crit("paracross.Commit crossAssetTransfer Tx failed", "error", err, "act", act, "txHash", common.ToHex(crossTxHash))
// return nil, err
// }
// clog.Debug("paracross.Commit crossAssetTransfer done", "act", act, "txHash", common.ToHex(crossTxHash))
// return receipt, nil
// }
//
// }
//
// //主链共识后,执行主链资产withdraw, 在支持CrossAssetTransfer之前使用此action
// if payload.Ty == pt.ParacrossActionAssetWithdraw {
// receiptWithdraw, err := a.assetWithdraw(payload.GetAssetWithdraw(), cross.Tx)
// if err != nil {
// clog.Crit("paracross.Commit withdraw Tx failed", "error", err, "txHash", common.ToHex(crossTxHash))
// return nil, errors.Cause(err)
// }
//
// clog.Debug("paracross.Commit WithdrawCoins", "txHash", common.ToHex(crossTxHash))
// return receiptWithdraw, nil
// }
// return nil, nil
//}
func rollbackCrossTxNew(a *action, cross *types.Transaction, crossTxHash []byte) (*types.Receipt, error) {
if !bytes.HasSuffix(cross.Execer, []byte(pt.ParaX)) {
return nil, nil
}
var payload pt.ParacrossAction
err := types.Decode(cross.Tx.Payload, &payload)
err := types.Decode(cross.Payload, &payload)
if err != nil {
clog.Crit("paracross.Commit.rollbackCrossTx Decode Tx failed", "error", err, "txHash", common.ToHex(crossTxHash))
return nil, err
}
if payload.Ty == pt.ParacrossActionCrossAssetTransfer {
act, err := getCrossAction(payload.GetCrossAssetTransfer(), string(cross.Tx.Execer))
act, err := getCrossAction(payload.GetCrossAssetTransfer(), string(cross.Execer))
if err != nil {
clog.Crit("paracross.Commit.rollbackCrossTx getCrossAction failed", "error", err, "txHash", common.ToHex(crossTxHash))
return nil, err
}
//主链共识后,平行链执行出错的主链资产transfer回滚
if act == pt.ParacrossMainAssetTransfer {
receipt, err := a.assetTransferRollback(payload.GetCrossAssetTransfer(), cross.Tx)
receipt, err := a.assetTransferRollback(payload.GetCrossAssetTransfer(), cross)
if err != nil {
clog.Crit("paracross.Commit crossAssetTransfer rbk failed", "error", err, "txHash", common.ToHex(crossTxHash))
return nil, errors.Cause(err)
......@@ -1094,7 +1137,7 @@ func rollbackCrossTx(a *action, cross *types.TransactionDetail, crossTxHash []by
}
//主链共识后,平行链执行出错的平行链资产withdraw回滚
if act == pt.ParacrossParaAssetWithdraw {
receipt, err := a.paraAssetWithdrawRollback(payload.GetCrossAssetTransfer(), cross.Tx)
receipt, err := a.paraAssetWithdrawRollback(payload.GetCrossAssetTransfer(), cross)
if err != nil {
clog.Crit("paracross.Commit rbk paraAssetWithdraw Tx failed", "error", err, "txHash", common.ToHex(crossTxHash))
return nil, errors.Cause(err)
......@@ -1115,7 +1158,7 @@ func rollbackCrossTx(a *action, cross *types.TransactionDetail, crossTxHash []by
ToAddr: cfg.To,
}
receipt, err := a.assetTransferRollback(transfer, cross.Tx)
receipt, err := a.assetTransferRollback(transfer, cross)
if err != nil {
clog.Crit("paracross.Commit rbk asset transfer Tx failed", "error", err, "txHash", common.ToHex(crossTxHash))
return nil, errors.Cause(err)
......@@ -1128,6 +1171,70 @@ func rollbackCrossTx(a *action, cross *types.TransactionDetail, crossTxHash []by
}
//func rollbackCrossTx(a *action, cross *types.TransactionDetail, crossTxHash []byte) (*types.Receipt, error) {
// if !bytes.HasSuffix(cross.Tx.Execer, []byte(pt.ParaX)) {
// return nil, nil
// }
// var payload pt.ParacrossAction
// err := types.Decode(cross.Tx.Payload, &payload)
// if err != nil {
// clog.Crit("paracross.Commit.rollbackCrossTx Decode Tx failed", "error", err, "txHash", common.ToHex(crossTxHash))
// return nil, err
// }
//
// if payload.Ty == pt.ParacrossActionCrossAssetTransfer {
// act, err := getCrossAction(payload.GetCrossAssetTransfer(), string(cross.Tx.Execer))
// if err != nil {
// clog.Crit("paracross.Commit.rollbackCrossTx getCrossAction failed", "error", err, "txHash", common.ToHex(crossTxHash))
// return nil, err
// }
// //主链共识后,平行链执行出错的主链资产transfer回滚
// if act == pt.ParacrossMainAssetTransfer {
// receipt, err := a.assetTransferRollback(payload.GetCrossAssetTransfer(), cross.Tx)
// if err != nil {
// clog.Crit("paracross.Commit crossAssetTransfer rbk failed", "error", err, "txHash", common.ToHex(crossTxHash))
// return nil, errors.Cause(err)
// }
//
// clog.Debug("paracross.Commit crossAssetTransfer rollbackCrossTx", "txHash", common.ToHex(crossTxHash), "mainHeight", a.height)
// return receipt, nil
// }
// //主链共识后,平行链执行出错的平行链资产withdraw回滚
// if act == pt.ParacrossParaAssetWithdraw {
// receipt, err := a.paraAssetWithdrawRollback(payload.GetCrossAssetTransfer(), cross.Tx)
// if err != nil {
// clog.Crit("paracross.Commit rbk paraAssetWithdraw Tx failed", "error", err, "txHash", common.ToHex(crossTxHash))
// return nil, errors.Cause(err)
// }
//
// clog.Debug("paracross.Commit paraAssetWithdraw rollbackCrossTx", "txHash", common.ToHex(crossTxHash), "mainHeight", a.height)
// return receipt, nil
// }
// }
//
// //主链共识后,平行链执行出错的主链资产transfer回滚
// if payload.Ty == pt.ParacrossActionAssetTransfer {
// cfg := payload.GetAssetTransfer()
// transfer := &pt.CrossAssetTransfer{
// AssetSymbol: cfg.Cointoken,
// Amount: cfg.Amount,
// Note: string(cfg.Note),
// ToAddr: cfg.To,
// }
//
// receipt, err := a.assetTransferRollback(transfer, cross.Tx)
// if err != nil {
// clog.Crit("paracross.Commit rbk asset transfer Tx failed", "error", err, "txHash", common.ToHex(crossTxHash))
// return nil, errors.Cause(err)
// }
//
// clog.Debug("paracross.Commit assetTransfer rollbackCrossTx", "txHash", common.ToHex(crossTxHash), "mainHeight", a.height)
// return receipt, nil
// }
// return nil, nil
//
//}
//无跨链交易高度列表是人为配置的,是确认的历史高度,是一种特殊处理,不会影响区块状态hash
//para.ignore.10-100.200-300
func isInIgnoreHeightList(str string, status *pt.ParacrossNodeStatus) (bool, error) {
......@@ -1245,7 +1352,7 @@ func checkIsIgnoreHeight(heightList []string, status *pt.ParacrossNodeStatus) (b
}
func getCrossTxHashsByRst(api client.QueueProtocolAPI, status *pt.ParacrossNodeStatus) ([][]byte, []byte, error) {
func getCrossTxsByRst(api client.QueueProtocolAPI, status *pt.ParacrossNodeStatus) ([]*types.Transaction, []byte, error) {
//支持带版本号的跨链交易bitmap
//1.如果等于0,是老版本的平行链,按老的方式处理. 2. 如果大于0等于ver,新版本且没有跨链交易,不需要处理. 3. 大于ver,说明有跨链交易按老的方式处理
if len(string(status.CrossTxResult)) == pt.ParaCrossStatusBitMapVerLen {
......@@ -1289,19 +1396,19 @@ func getCrossTxHashsByRst(api client.QueueProtocolAPI, status *pt.ParacrossNodeS
for _, tx := range paraAllTxs {
baseHashs = append(baseHashs, tx.Hash())
}
paraCrossHashs := FilterParaCrossTxHashes(paraAllTxs)
paraCrossTxs := FilterParaCrossTxs(paraAllTxs)
var paraCrossHashs [][]byte
for _, tx := range paraCrossTxs {
paraCrossHashs = append(paraCrossHashs, tx.Hash())
}
crossRst := util.CalcBitMapByBitMap(paraCrossHashs, baseHashs, rst)
return paraCrossHashs, crossRst, nil
return paraCrossTxs, crossRst, nil
}
func getCrossTxHashs(api client.QueueProtocolAPI, status *pt.ParacrossNodeStatus) ([][]byte, []byte, error) {
func getCrossTxs(api client.QueueProtocolAPI, status *pt.ParacrossNodeStatus) ([]*types.Transaction, []byte, error) {
cfg := api.GetConfig()
if pt.IsParaForkHeight(cfg, status.MainBlockHeight, pt.ForkLoopCheckCommitTxDone) {
return getCrossTxHashsByRst(api, status)
}
if !pt.IsParaForkHeight(cfg, status.MainBlockHeight, pt.ForkCommitTx) {
return status.CrossTxHashs, status.CrossTxResult, nil
return getCrossTxsByRst(api, status)
}
if len(status.CrossTxHashs) == 0 {
......@@ -1327,13 +1434,35 @@ func getCrossTxHashs(api client.QueueProtocolAPI, status *pt.ParacrossNodeStatus
if err != nil {
return nil, nil, err
}
if !pt.IsParaForkHeight(cfg, status.MainBlockHeight, pt.ForkCommitTx) {
// 直接按照status.CrossTxHashs指定的哈希列表查找交易
paraCrossTxs := make([]*types.Transaction, len(status.CrossTxHashs))
txs := blockDetail.Block.Txs
for i, hash := range status.CrossTxHashs {
for j, tx := range txs {
if bytes.Equal(hash, tx.Hash()) {
paraCrossTxs[i] = tx
txs = txs[j:]
break
}
}
}
if len(paraCrossTxs) != len(status.CrossTxHashs) {
return nil, nil, types.ErrTxNotExist
}
return paraCrossTxs, status.CrossTxResult, nil
}
//校验
paraBaseTxs := FilterTxsForPara(cfg, blockDetail.FilterParaTxsByTitle(cfg, status.Title))
paraCrossHashs := FilterParaCrossTxHashes(paraBaseTxs)
paraCrossTxs := FilterParaCrossTxs(paraBaseTxs)
var baseHashs [][]byte
for _, tx := range paraBaseTxs {
baseHashs = append(baseHashs, tx.Hash())
}
var paraCrossHashs [][]byte
for _, tx := range paraCrossTxs {
paraCrossHashs = append(paraCrossHashs, tx.Hash())
}
baseCheckTxHash := CalcTxHashsHash(baseHashs)
crossCheckHash := CalcTxHashsHash(paraCrossHashs)
if !bytes.Equal(status.CrossTxHashs[0], crossCheckHash) {
......@@ -1357,42 +1486,32 @@ func getCrossTxHashs(api client.QueueProtocolAPI, status *pt.ParacrossNodeStatus
return nil, nil, types.ErrInvalidParam
}
return paraCrossHashs, rst, nil
return paraCrossTxs, rst, nil
}
func crossTxProc(a *action, txHash []byte, fn func(*action, *types.TransactionDetail, []byte) (*types.Receipt, error)) (*types.Receipt, error) {
tx, err := GetTx(a.api, txHash)
if err != nil {
clog.Crit("paracross.Commit Load Tx failed", "error", err, "txHash", common.ToHex(txHash))
return nil, err
}
if tx == nil {
clog.Error("paracross.Commit Load Tx nil", "error", err, "txHash", common.ToHex(txHash))
return nil, types.ErrHashNotExist
}
receiptCross, err := fn(a, tx, txHash)
if err != nil {
clog.Error("paracross.Commit execCrossTx", "error", err)
return nil, errors.Cause(err)
func getCrossTxHashs(api client.QueueProtocolAPI, status *pt.ParacrossNodeStatus) ([][]byte, []byte, error) {
txs, crossRst, err := getCrossTxs(api, status)
var crossTxHashs [][]byte
for _, tx := range txs {
crossTxHashs = append(crossTxHashs, tx.Hash())
}
return receiptCross, nil
return crossTxHashs, crossRst, err
}
func (a *action) execCrossTxs(status *pt.ParacrossNodeStatus) (*types.Receipt, error) {
var receipt types.Receipt
crossTxHashs, crossTxResult, err := getCrossTxHashs(a.api, status)
crossTxs, crossTxResult, err := getCrossTxs(a.api, status)
if err != nil {
clog.Error("paracross.Commit getCrossTxHashs", "err", err.Error())
return nil, err
}
for i := 0; i < len(crossTxHashs); i++ {
clog.Debug("paracross.Commit commitDone", "do cross number", i, "hash", common.ToHex(crossTxHashs[i]),
for i := 0; i < len(crossTxs); i++ {
clog.Debug("paracross.Commit commitDone", "do cross number", i, "hash", common.ToHex(crossTxs[i].Hash()),
"res", util.BitMapBit(crossTxResult, uint32(i)))
if util.BitMapBit(crossTxResult, uint32(i)) {
receiptCross, err := crossTxProc(a, crossTxHashs[i], execCrossTx)
//receiptCross, err := crossTxProc(a, crossTxHashs[i], execCrossTx)
receiptCross, err := execCrossTxNew(a, crossTxs[i], crossTxs[i].Hash())
if err != nil {
clog.Error("paracross.Commit execCrossTx", "para title", status.Title, "para height", status.Height,
"para tx index", i, "error", err)
......@@ -1401,15 +1520,16 @@ func (a *action) execCrossTxs(status *pt.ParacrossNodeStatus) (*types.Receipt, e
if receiptCross == nil {
continue
}
clog.Debug("paracross.Commit commitDone.title ok ", "title", status.Title, "height", status.Height, "main", a.height, "i", i, "hash", common.ToHex(crossTxHashs[i]))
clog.Debug("paracross.Commit commitDone.title ok ", "title", status.Title, "height", status.Height, "main", a.height, "i", i, "hash", common.ToHex(crossTxs[i].Hash()))
receipt.KV = append(receipt.KV, receiptCross.KV...)
receipt.Logs = append(receipt.Logs, receiptCross.Logs...)
} else {
clog.Error("paracross.Commit commitDone", "do cross number", i, "hash",
common.ToHex(crossTxHashs[i]), "para res", util.BitMapBit(crossTxResult, uint32(i)))
common.ToHex(crossTxs[i].Hash()), "para res", util.BitMapBit(crossTxResult, uint32(i)))
cfg := a.api.GetConfig()
if cfg.IsDappFork(a.height, pt.ParaX, pt.ForkParaAssetTransferRbk) {
receiptCross, err := crossTxProc(a, crossTxHashs[i], rollbackCrossTx)
//receiptCross, err := crossTxProc(a, crossTxHashs[i], rollbackCrossTx)
receiptCross, err := rollbackCrossTxNew(a, crossTxs[i], crossTxs[i].Hash())
if err != nil {
clog.Error("paracross.Commit rollbackCrossTx", "para title", status.Title, "para height", status.Height,
"para tx index", i, "error", err)
......@@ -1418,7 +1538,7 @@ func (a *action) execCrossTxs(status *pt.ParacrossNodeStatus) (*types.Receipt, e
if receiptCross == nil {
continue
}
clog.Debug("paracross.Commit commitDone.title rbk", "title", status.Title, "height", status.Height, "main", a.height, "i", i, "hash", common.ToHex(crossTxHashs[i]))
clog.Debug("paracross.Commit commitDone.title rbk", "title", status.Title, "height", status.Height, "main", a.height, "i", i, "hash", common.ToHex(crossTxs[i].Hash()))
receipt.KV = append(receipt.KV, receiptCross.KV...)
receipt.Logs = append(receipt.Logs, receiptCross.Logs...)
}
......@@ -1426,6 +1546,7 @@ func (a *action) execCrossTxs(status *pt.ParacrossNodeStatus) (*types.Receipt, e
}
return &receipt, nil
}
func (a *action) assetTransferMainCheck(cfg *types.Chain33Config, transfer *types.AssetsTransfer) error {
......
......@@ -102,6 +102,17 @@ func FilterTxsForPara(cfg *types.Chain33Config, main *types.ParaTxDetail) []*typ
return txs
}
// FilterParaCrossTxs only all para chain cross txs like xx.paracross exec
func FilterParaCrossTxs(txs []*types.Transaction) []*types.Transaction {
var paraCrossTxs []*types.Transaction
for _, tx := range txs {
if types.IsParaExecName(string(tx.Execer)) && bytes.HasSuffix(tx.Execer, []byte(pt.ParaX)) {
paraCrossTxs = append(paraCrossTxs, tx)
}
}
return paraCrossTxs
}
// FilterParaCrossTxHashes only all para chain cross txs like xx.paracross exec
func FilterParaCrossTxHashes(txs []*types.Transaction) [][]byte {
var txHashs [][]byte
......
......@@ -64,12 +64,12 @@ func init() {
//InitFork ...
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork(ParaX, "Enable", 0)
cfg.RegisterDappFork(ParaX, "ForkParacrossWithdrawFromParachain", 1298600)
cfg.RegisterDappFork(ParaX, ForkCommitTx, 1850000)
cfg.RegisterDappFork(ParaX, ForkLoopCheckCommitTxDone, 3230000)
cfg.RegisterDappFork(ParaX, ForkParaAssetTransferRbk, 4500000)
cfg.RegisterDappFork(ParaX, ForkParaSupervision, 6000000)
cfg.RegisterDappFork(ParaX, ForkParaAutonomySuperGroup, 10200000)
cfg.RegisterDappFork(ParaX, "ForkParacrossWithdrawFromParachain", 0)
cfg.RegisterDappFork(ParaX, ForkCommitTx, 0)
cfg.RegisterDappFork(ParaX, ForkLoopCheckCommitTxDone, 0)
cfg.RegisterDappFork(ParaX, ForkParaAssetTransferRbk, 0)
cfg.RegisterDappFork(ParaX, ForkParaSupervision, 0)
cfg.RegisterDappFork(ParaX, ForkParaAutonomySuperGroup, 0)
//只在平行链启用
cfg.RegisterDappFork(ParaX, ForkParaSelfConsStages, types.MaxHeight)
......
......@@ -47,7 +47,7 @@ func init() {
//InitFork ...
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork(PrivacyX, "Enable", 980000)
cfg.RegisterDappFork(PrivacyX, "Enable", 0)
}
//InitExecutor ...
......
......@@ -111,7 +111,7 @@ func (val *QbftNode) Query_GetPerfStat(in *pty.ReqQbftPerfStat) (types.Message,
startHeader := startInfo.Block.Header
endHeader := endInfo.Block.Header
totalTx := endHeader.TotalTxs - startHeader.TotalTxs
totalTx := endHeader.TotalTxs - startHeader.TotalTxs + startHeader.NumTxs
totalBlock := endHeader.Height - startHeader.Height + 1
totalSecond := endHeader.Time - startHeader.Time + 1
return &pty.QbftPerfStat{
......
......@@ -56,7 +56,7 @@ func init() {
//InitFork ...
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork(RelayX, "Enable", 570000)
cfg.RegisterDappFork(RelayX, "Enable", 0)
}
//InitExecutor ...
......
......@@ -9,9 +9,8 @@ import (
"errors"
"fmt"
"math/rand"
"testing"
"strings"
"testing"
"github.com/33cn/chain33/client"
"github.com/33cn/chain33/common/address"
......@@ -250,6 +249,8 @@ func TestExecDelLocalBackup(t *testing.T) {
func constructRetrieveInstance() drivers.Driver {
cfgstring := strings.Replace(types.GetDefaultCfgstring(), "Title=\"local\"", "Title=\"chain33\"", 1)
chainTestCfg := types.NewChain33Config(cfgstring)
chainTestCfg.SetDappFork(rt.RetrieveX, rt.ForkRetriveX, 180000)
chainTestCfg.SetDappFork(rt.RetrieveX, rt.ForkRetriveAssetX, 3150000)
Init(rt.RetrieveX, chainTestCfg, nil)
q := queue.New("channel")
q.SetConfig(chainTestCfg)
......
......@@ -20,8 +20,8 @@ func init() {
//InitFork ...
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork(RetrieveX, "Enable", 0)
cfg.RegisterDappFork(RetrieveX, ForkRetriveX, 180000)
cfg.RegisterDappFork(RetrieveX, ForkRetriveAssetX, 3150000)
cfg.RegisterDappFork(RetrieveX, ForkRetriveX, 0)
cfg.RegisterDappFork(RetrieveX, ForkRetriveAssetX, 0)
}
//InitExecutor ...
......
......@@ -17,6 +17,7 @@ EventTransfer -> 转移资产
//nofee transaction will not pack into block
import (
"bytes"
"fmt"
log "github.com/33cn/chain33/common/log/log15"
......@@ -31,6 +32,7 @@ var driverName = "ticket"
// Init initial
func Init(name string, cfg *types.Chain33Config, sub []byte) {
drivers.Register(cfg, GetName(), newTicket, cfg.GetDappFork(driverName, "Enable"))
drivers.RegisterKVExpiredChecker(ty.TicketX, expiredKVChecker)
InitExecType()
}
......@@ -193,3 +195,23 @@ func (t *Ticket) CheckTx(tx *types.Transaction, index int) error {
func (t *Ticket) CheckReceiptExecOk() bool {
return true
}
// 自定义接口,用于删除不再需要保存的kv
// 比如 ticket 已经 close 之后就废弃了,可以删除
func expiredKVChecker(key, value []byte) bool {
// 由于 ticketBindKeyPrefix 包含了 ticketKeyPrefix,所以需要多做一次检查
if bytes.HasPrefix(key, ticketBindKeyPrefix) {
return false
}
if !bytes.HasPrefix(key, ticketKeyPrefix) {
return false
}
var tk ty.Ticket
if err := types.Decode(value, &tk); err != nil {
return false
}
if tk.Status == ty.TicketClosed {
return true
}
return false
}
......@@ -29,6 +29,11 @@ var tlog = log.New("module", "ticket.db")
//var genesisKey = []byte("mavl-acc-genesis")
//var addrSeed = []byte("address seed bytes for public key")
var (
ticketKeyPrefix = []byte("mavl-ticket-")
ticketBindKeyPrefix = []byte("mavl-ticket-tbind-")
)
// DB db
type DB struct {
ty.Ticket
......@@ -106,14 +111,14 @@ func (t *DB) Save(db dbm.KV) {
//Key address to save key
func Key(id string) (key []byte) {
key = append(key, []byte("mavl-ticket-")...)
key = append(key, ticketKeyPrefix...)
key = append(key, []byte(id)...)
return key
}
// BindKey bind key
func BindKey(id string) (key []byte) {
key = append(key, []byte("mavl-ticket-tbind-")...)
key = append(key, ticketBindKeyPrefix...)
key = append(key, []byte(id)...)
return key
}
......
......@@ -415,10 +415,12 @@ Enable=0
[fork.sub.issuance]
Enable=0
ForkIssuanceTableUpdate=0
ForkIssuancePrecision=0
[fork.sub.collateralize]
Enable=0
ForkCollateralizeTableUpdate=0
ForkCollateralizePrecision=0
[fork.sub.qbftNode]
Enable=0
......
......@@ -78,8 +78,8 @@ func init() {
//InitFork ...
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork(TicketX, "Enable", 0)
cfg.RegisterDappFork(TicketX, "ForkTicketId", 1062000)
cfg.RegisterDappFork(TicketX, "ForkTicketVrf", 1770000)
cfg.RegisterDappFork(TicketX, "ForkTicketId", 0)
cfg.RegisterDappFork(TicketX, "ForkTicketVrf", 0)
}
//InitExecutor ...
......
......@@ -437,6 +437,8 @@ func getprivkey(key string) crypto.PrivKey {
func TestToken_validSymbolWithHeight(t *testing.T) {
cfg := types.NewChain33Config(strings.Replace(types.GetDefaultCfgstring(), "Title=\"local\"", "Title=\"chain33\"", 1))
cfg.SetDappFork(pty.TokenX, pty.ForkBadTokenSymbolX, 184000)
cfg.SetDappFork(pty.TokenX, pty.ForkTokenSymbolWithNumberX, 1298600)
forkBadTokenSymbol := cfg.GetDappFork(pty.TokenX, pty.ForkBadTokenSymbolX)
forkTokenSymbolWithNumber := cfg.GetDappFork(pty.TokenX, pty.ForkTokenSymbolWithNumberX)
t.Log("x", "1", forkBadTokenSymbol, "2", forkTokenSymbolWithNumber)
......
......@@ -46,6 +46,7 @@ var (
func TestToken(t *testing.T) {
cfg := types.NewChain33Config(strings.Replace(types.GetDefaultCfgstring(), "Title=\"local\"", "Title=\"chain33\"", 1))
cfg.SetDappFork(pty.TokenX, pty.ForkTokenCheckX, 1600000)
Init(pty.TokenX, cfg, nil)
tokenTotal := int64(10000 * 1e8)
tokenBurn := int64(10 * 1e8)
......
......@@ -23,12 +23,12 @@ func init() {
//InitFork ...
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork(TokenX, "Enable", 100899)
cfg.RegisterDappFork(TokenX, ForkTokenBlackListX, 190000)
cfg.RegisterDappFork(TokenX, ForkBadTokenSymbolX, 184000)
cfg.RegisterDappFork(TokenX, ForkTokenPriceX, 560000)
cfg.RegisterDappFork(TokenX, ForkTokenSymbolWithNumberX, 1298600)
cfg.RegisterDappFork(TokenX, ForkTokenCheckX, 1600000)
cfg.RegisterDappFork(TokenX, "Enable", 0)
cfg.RegisterDappFork(TokenX, ForkTokenBlackListX, 0)
cfg.RegisterDappFork(TokenX, ForkBadTokenSymbolX, 0)
cfg.RegisterDappFork(TokenX, ForkTokenPriceX, 0)
cfg.RegisterDappFork(TokenX, ForkTokenSymbolWithNumberX, 0)
cfg.RegisterDappFork(TokenX, ForkTokenCheckX, 0)
}
//InitExecutor ...
......
......@@ -59,12 +59,12 @@ func init() {
//InitFork ...
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork(TradeX, "Enable", 100899)
cfg.RegisterDappFork(TradeX, ForkTradeBuyLimitX, 301000)
cfg.RegisterDappFork(TradeX, ForkTradeAssetX, 1010000)
cfg.RegisterDappFork(TradeX, ForkTradeIDX, 1450000)
cfg.RegisterDappFork(TradeX, ForkTradeFixAssetDBX, 2500000)
cfg.RegisterDappFork(TradeX, ForkTradePriceX, 3150000)
cfg.RegisterDappFork(TradeX, "Enable", 0)
cfg.RegisterDappFork(TradeX, ForkTradeBuyLimitX, 0)
cfg.RegisterDappFork(TradeX, ForkTradeAssetX, 0)
cfg.RegisterDappFork(TradeX, ForkTradeIDX, 0)
cfg.RegisterDappFork(TradeX, ForkTradeFixAssetDBX, 0)
cfg.RegisterDappFork(TradeX, ForkTradePriceX, 0)
}
//InitExecutor ...
......
......@@ -30,8 +30,8 @@ func init() {
func InitFork(cfg *types.Chain33Config) {
name = UnfreezeX
cfg.RegisterDappFork(name, "Enable", 0)
cfg.RegisterDappFork(name, ForkTerminatePartX, 1298600)
cfg.RegisterDappFork(name, ForkUnfreezeIDX, 1450000)
cfg.RegisterDappFork(name, ForkTerminatePartX, 0)
cfg.RegisterDappFork(name, ForkUnfreezeIDX, 0)
}
//InitExecutor ...
......
......@@ -67,7 +67,7 @@ func init() {
//InitFork ...
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork("store-kvmvccmavl", "ForkKvmvccmavl", 187*10000)
cfg.RegisterDappFork("store-kvmvccmavl", "ForkKvmvccmavl", 0)
}
// KVmMavlStore provide kvmvcc and mavl store interface implementation
......@@ -81,8 +81,9 @@ type KVmMavlStore struct {
type subKVMVCCConfig struct {
EnableMVCCIter bool `json:"enableMVCCIter"`
EnableMVCCPrune bool `json:"enableMVCCPrune"`
PruneHeight int32 `json:"pruneHeight"`
PruneHeight int32 `json:"pruneHeight"` //每PruneHeight高度做一次状态精简
EnableEmptyBlockHandle bool `json:"enableEmptyBlockHandle"`
ReservedHeight int64 `json:"reservedHeight"` //保留最新的ReservedHeight个区块的状态数据
}
type subMavlConfig struct {
......@@ -114,6 +115,8 @@ type subConfig struct {
TkCloseCacheLen int32 `json:"tkCloseCacheLen"`
// 使能空块处理
EnableEmptyBlockHandle bool `json:"enableEmptyBlockHandle"`
//保留的状态数据的高度
ReservedHeight int64 `json:"reservedHeight"`
}
// New construct KVMVCCStore module
......@@ -128,6 +131,7 @@ func New(cfg *types.Store, sub []byte, chain33cfg *types.Chain33Config) queue.Mo
subKVMVCCcfg.EnableMVCCPrune = subcfg.EnableMVCCPrune
subKVMVCCcfg.PruneHeight = subcfg.PruneMVCCHeight
subKVMVCCcfg.EnableEmptyBlockHandle = subcfg.EnableEmptyBlockHandle
subKVMVCCcfg.ReservedHeight = subcfg.ReservedHeight
subMavlcfg.EnableMavlPrefix = subcfg.EnableMavlPrefix
subMavlcfg.EnableMVCC = subcfg.EnableMVCC
......@@ -171,6 +175,7 @@ func New(cfg *types.Store, sub []byte, chain33cfg *types.Chain33Config) queue.Mo
func (kvmMavls *KVmMavlStore) Close() {
quit = true
wg.Wait()
kmlog.Info("store wait group done")
kvmMavls.KVMVCCStore.Close()
kvmMavls.MavlStore.Close()
kvmMavls.BaseStore.Close()
......
......@@ -664,7 +664,8 @@ func TestPruning(t *testing.T) {
hashes = append(hashes, hash)
}
pruningMVCC(store.GetDB(), 99, &KVMCCCConfig{PruneHeight: 10})
pruningMVCCData(store.GetDB(), 80)
pruningMVCCMeta(store.GetDB(), 80)
//check
getDatas := &types.StoreGet{
......
......@@ -6,15 +6,14 @@ package kvmvccmavl
import (
"bytes"
"fmt"
"strconv"
"sync/atomic"
"time"
"github.com/33cn/chain33/common"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/queue"
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
"github.com/golang/protobuf/proto"
)
......@@ -22,9 +21,6 @@ import (
const (
pruningStateStart = 1
pruningStateEnd = 0
onceScanCount = 10000 // 单次扫描数目
onceCount = 1000 // 容器长度
levelPruningHeight = 100 * 10000
defaultPruneHeight = 10000 // 每个10000裁剪一次
)
......@@ -36,31 +32,23 @@ var (
var (
//同common/db中的mvcc相关的定义保持一致
mvccPrefix = []byte(".-mvcc-.")
//mvccMeta = append(mvccPrefix, []byte("m.")...)
mvccMeta = append(mvccPrefix, []byte("m.")...)
mvccData = append(mvccPrefix, []byte("d.")...)
//mvccLast = append(mvccPrefix, []byte("l.")...)
//mvccMetaVersion = append(mvccMeta, []byte("version.")...)
//mvccMetaVersionKeyList = append(mvccMeta, []byte("versionkl.")...)
mvccMetaVersion = append(mvccMeta, []byte("version.")...)
mvccMetaVersionKeyList = append(mvccMeta, []byte("versionkl.")...)
// for empty block
rdmHashPrefix = append(mvccPrefix, []byte("rdm.")...)
)
// KVMCCCConfig KVMCCC config
type KVMCCCConfig struct {
EnableMVCCIter bool
EnableMVCCPrune bool
PruneHeight int32
EnableEmptyBlockHandle bool
}
// KVMVCCStore provide kvmvcc store interface implementation
type KVMVCCStore struct {
db dbm.DB
mvcc dbm.MVCC
kvsetmap map[string][]*types.KeyValue
sync bool
kvmvccCfg *KVMCCCConfig
kvmvccCfg *subKVMVCCConfig
}
// NewKVMVCC construct KVMVCCStore module
......@@ -72,16 +60,10 @@ func NewKVMVCC(sub *subKVMVCCConfig, db dbm.DB) *KVMVCCStore {
if sub.PruneHeight == 0 {
sub.PruneHeight = defaultPruneHeight
}
kvmvccCfg := &KVMCCCConfig{
EnableMVCCIter: sub.EnableMVCCIter,
EnableMVCCPrune: sub.EnableMVCCPrune,
PruneHeight: sub.PruneHeight,
EnableEmptyBlockHandle: sub.EnableEmptyBlockHandle,
}
if kvmvccCfg.EnableMVCCIter {
kvs = &KVMVCCStore{db, dbm.NewMVCCIter(db), make(map[string][]*types.KeyValue), false, kvmvccCfg}
if sub.EnableMVCCIter {
kvs = &KVMVCCStore{db: db, mvcc: dbm.NewMVCCIter(db), kvsetmap: make(map[string][]*types.KeyValue), kvmvccCfg: sub}
} else {
kvs = &KVMVCCStore{db, dbm.NewMVCC(db), make(map[string][]*types.KeyValue), false, kvmvccCfg}
kvs = &KVMVCCStore{db: db, mvcc: dbm.NewMVCC(db), kvsetmap: make(map[string][]*types.KeyValue), kvmvccCfg: sub}
}
return kvs
}
......@@ -148,11 +130,9 @@ func (mvccs *KVMVCCStore) MemSet(datas *types.StoreSet, hash []byte, sync bool)
mvccs.sync = sync
// 进行裁剪
if mvccs.kvmvccCfg != nil && mvccs.kvmvccCfg.EnableMVCCPrune &&
!isPruning() && mvccs.kvmvccCfg.PruneHeight != 0 &&
datas.Height%int64(mvccs.kvmvccCfg.PruneHeight) == 0 &&
datas.Height/int64(mvccs.kvmvccCfg.PruneHeight) > 1 {
!isPruning() && datas.Height%int64(mvccs.kvmvccCfg.PruneHeight) == 0 {
wg.Add(1)
go pruning(mvccs.db, datas.Height, mvccs.kvmvccCfg)
go mvccs.pruningMVCC(datas.Height)
}
return hash, nil
}
......@@ -421,11 +401,9 @@ func (mvccs *KVMVCCStore) MemSetRdm(datas *types.StoreSet, mavlHash []byte, sync
// 进行裁剪
if mvccs.kvmvccCfg != nil && mvccs.kvmvccCfg.EnableMVCCPrune &&
!isPruning() && mvccs.kvmvccCfg.PruneHeight != 0 &&
datas.Height%int64(mvccs.kvmvccCfg.PruneHeight) == 0 &&
datas.Height/int64(mvccs.kvmvccCfg.PruneHeight) > 1 {
!isPruning() && datas.Height%int64(mvccs.kvmvccCfg.PruneHeight) == 0 {
wg.Add(1)
go pruning(mvccs.db, datas.Height, mvccs.kvmvccCfg)
go mvccs.pruningMVCC(datas.Height)
}
return hash, nil
}
......@@ -455,94 +433,158 @@ func calcRdmKey(hash []byte, height int64) []byte {
}
/*裁剪-------------------------------------------*/
func pruning(db dbm.DB, height int64, KVmvccCfg *KVMCCCConfig) {
func (mvccs *KVMVCCStore) pruningMVCC(curHeight int64) {
defer wg.Done()
pruningMVCC(db, height, KVmvccCfg)
}
func pruningMVCC(db dbm.DB, height int64, KVmvccCfg *KVMCCCConfig) {
safeHeight := curHeight - mvccs.kvmvccCfg.ReservedHeight
if safeHeight <= 0 {
return
}
setPruning(pruningStateStart)
defer setPruning(pruningStateEnd)
start := time.Now()
pruningFirst(db, height, KVmvccCfg)
end := time.Now()
kmlog.Debug("pruningMVCC", "height", height, "cost", end.Sub(start))
pruningMVCCDappExpired(mvccs.db, safeHeight)
kmlog.Info("pruningMVCCDappExpired", "current height", curHeight, "cost", time.Since(start))
pruningMVCCData(mvccs.db, safeHeight)
kmlog.Info("pruningMVCCData", "current height", curHeight, "cost", time.Since(start))
pruningMVCCMeta(mvccs.db, safeHeight)
kmlog.Info("pruningMVCCMeta", "current height", curHeight, "cost", time.Since(start))
}
func pruningFirst(db dbm.DB, curHeight int64, KVmvccCfg *KVMCCCConfig) {
func pruningMVCCData(db dbm.DB, safeHeight int64) {
it := db.Iterator(mvccData, nil, true)
defer it.Close()
var mp map[string][]int64
count := 0
batch := db.NewBatch(true)
newKey := []byte("--.xxx.--")
batch := db.NewBatch(false)
defer dbm.MustWrite(batch)
for it.Rewind(); it.Valid(); it.Next() {
if quit {
//该处退出
return
}
if mp == nil {
mp = make(map[string][]int64, onceCount)
}
key, height, err := getKeyVersion(it.Key())
if err != nil {
continue
}
if curHeight < height+levelPruningHeight &&
curHeight >= height+int64(KVmvccCfg.PruneHeight) {
mp[string(key)] = append(mp[string(key)], height)
count++
if height >= safeHeight {
continue
}
if len(mp) >= onceCount-1 || count > onceScanCount {
deleteOldKV(mp, curHeight, batch, KVmvccCfg)
mp = nil
count = 0
if bytes.Compare(key, newKey) != 0 {
newKey = make([]byte, len(key))
copy(newKey, key)
continue
}
batch.Delete(it.Key())
if batch.ValueSize() > 1<<20 {
dbm.MustWrite(batch)
batch.Reset()
}
if len(mp) > 0 {
deleteOldKV(mp, curHeight, batch, KVmvccCfg)
mp = nil
_ = mp
}
}
func deleteOldKV(mp map[string][]int64, curHeight int64, batch dbm.Batch, KVmvccCfg *KVMCCCConfig) {
if len(mp) == 0 {
// TODO:
// 合约里自定义规则用于检查哪些kv对是已经废弃的
// 对于定义过规则的合约,这里会遍历该合约所有的kv对,然后合约内部检查该kv对是否已经废弃
// 更高效的做法是仅遍历指定合约里可能废弃的那些key(通过进一步指定prefix实现),但通用性会变差
// 现阶段效率差不多,暂时不做进一步优化
func pruningMVCCDappExpired(db dbm.DB, safeHeight int64) {
names := dapp.KVExpiredCheckerList()
for _, name := range names {
pruneDapp(db, name, safeHeight)
}
}
func pruneDapp(db dbm.DB, name string, safeHeight int64) {
checkFunc, ok := dapp.LoadKVExpiredChecker(name)
if !ok {
return
}
batch.Reset()
for key, vals := range mp {
if len(vals) > 1 && vals[1] != vals[0] { //防止相同高度时候出现的误删除
for _, val := range vals[1:] { //从第二个开始判断
if curHeight >= val+int64(KVmvccCfg.PruneHeight) {
batch.Delete(genKeyVersion([]byte(key), val)) // 删除老版本key
if batch.ValueSize() > batchDataSize {
var prefix []byte
prefix = append(prefix, mvccData...)
prefix = append(prefix, "mavl-"+name...)
it := db.Iterator(prefix, nil, true)
defer it.Close()
for it.Rewind(); it.Valid(); it.Next() {
if quit {
//该处退出
return
}
key, height, err := getKeyVersion(it.Key())
if err != nil {
continue
}
if height > safeHeight {
continue
}
if checkFunc(key, it.Value()) {
deleteKeyAllVersion(db, key)
}
}
}
func deleteKeyAllVersion(db dbm.DB, key []byte) {
start := append(mvccData, key...)
it := db.Iterator(start, nil, false)
defer it.Close()
batch := db.NewBatch(false)
for it.Rewind(); it.Valid(); it.Next() {
batch.Delete(it.Key())
if batch.ValueSize() > 1<<20 {
dbm.MustWrite(batch)
batch.Reset()
}
}
dbm.MustWrite(batch)
}
func pruningMVCCMeta(db dbm.DB, height int64) {
pruningMVCCMetaVersion(db, height)
pruningMVCCMetaVersionKeyList(db, height)
}
func pruningMVCCMetaVersion(db dbm.DB, height int64) {
startPrefix := append(mvccMetaVersion, pad(0)...)
endPrefix := append(mvccMetaVersion, pad(height)...)
it := db.Iterator(startPrefix, endPrefix, false)
defer it.Close()
batch := db.NewBatch(false)
for it.Rewind(); it.Valid(); it.Next() {
if quit {
//该处退出
return
}
batch.Delete(it.Key())
batch.Delete(append(mvccMeta, it.Value()...))
if batch.ValueSize() > 1<<20 {
dbm.MustWrite(batch)
batch.Reset()
}
delete(mp, key)
}
dbm.MustWrite(batch)
_ = db.CompactRange(startPrefix, endPrefix)
}
func genKeyVersion(key []byte, height int64) []byte {
b := append([]byte{}, mvccData...)
newkey := append(b, key...)
newkey = append(newkey, []byte(".")...)
newkey = append(newkey, pad(height)...)
return newkey
func pruningMVCCMetaVersionKeyList(db dbm.DB, height int64) {
startPrefix := append(mvccMetaVersionKeyList, pad(0)...)
endPrefix := append(mvccMetaVersionKeyList, pad(height)...)
it := db.Iterator(startPrefix, endPrefix, false)
defer it.Close()
batch := db.NewBatch(false)
for it.Rewind(); it.Valid(); it.Next() {
if quit {
//该处退出
return
}
batch.Delete(it.Key())
if batch.ValueSize() > 1<<20 {
dbm.MustWrite(batch)
batch.Reset()
}
}
dbm.MustWrite(batch)
_ = db.CompactRange(startPrefix, endPrefix)
}
func getKeyVersion(vsnKey []byte) ([]byte, int64, error) {
if !bytes.Contains(vsnKey, mvccData) {
return nil, 0, types.ErrSize
}
if len(vsnKey) < len(mvccData)+1+20 {
return nil, 0, types.ErrSize
}
......@@ -557,12 +599,15 @@ func getKeyVersion(vsnKey []byte) ([]byte, int64, error) {
}
func pad(version int64) []byte {
s := fmt.Sprintf("%020d", version)
return []byte(s)
//equals to `[]byte(fmt.Sprintf("%020d", version))`
sInt := strconv.FormatInt(version, 10)
result := []byte("00000000000000000000")
copy(result[20-len(sInt):], sInt)
return result
}
func isPruning() bool {
return atomic.LoadInt32(&pruningState) == 1
return atomic.LoadInt32(&pruningState) == pruningStateStart
}
func setPruning(state int32) {
......
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