Commit 8560f422 authored by 张振华's avatar 张振华

Merge branch 'master' into guess-rpc-test

parents 0de07833 9332bf5a
......@@ -198,13 +198,14 @@ func (client *client) InitBlock() {
}
if block == nil {
startSeq := client.GetStartSeq(startHeight)
startSeq, mainHash := client.GetStartSeq(startHeight)
// 创世区块
newblock := &types.Block{}
newblock.Height = 0
newblock.BlockTime = genesisBlockTime
newblock.ParentHash = zeroHash[:]
newblock.MainHash = zeroHash[:]
newblock.MainHash = mainHash
newblock.MainHeight = startHeight
tx := client.CreateGenesisTx()
newblock.Txs = tx
newblock.TxHash = merkle.CalcMerkleRoot(newblock.Txs)
......@@ -219,9 +220,9 @@ func (client *client) InitBlock() {
}
// GetStartSeq get startSeq in mainchain
func (client *client) GetStartSeq(height int64) int64 {
func (client *client) GetStartSeq(height int64) (int64, []byte) {
if height == 0 {
return 0
return 0, nil
}
lastHeight, err := client.GetLastHeightOnMainChain()
......@@ -248,12 +249,12 @@ func (client *client) GetStartSeq(height int64) int64 {
hint.Stop()
plog.Info(fmt.Sprintf("lastHeight more than %d blocks after startHeight", minBlockNum), "lastHeight", lastHeight, "startHeight", height)
seq, err := client.GetSeqByHeightOnMainChain(height)
seq, hash, err := client.GetSeqByHeightOnMainChain(height)
if err != nil {
panic(err)
}
plog.Info("the start sequence in mainchain", "startHeight", height, "startSeq", seq)
return seq
return seq, hash
}
func (client *client) CreateGenesisTx() (ret []*types.Transaction) {
......@@ -306,6 +307,31 @@ func (client *client) GetBlockByHeight(height int64) (*types.Block, error) {
return blockDetails.Items[0].Block, nil
}
// 获取上一个平行链对应主链seq,hash信息
// 对于平行链创世区块特殊场景:
// 1,创世区块seq从-1开始,也就是从主链0高度同步区块,主链seq从0开始,平行链对seq=0的区块校验时候做特殊处理,不校验parentHash
// 2,创世区块seq不是-1, 也就是从主链seq=n高度同步区块,此时创世区块记录了起始高度对应的主链hash,通过hash获取当前seq,然后创世区块需要倒退一个seq,lastSeq=n-1,
// 因为对于云端主链节点,创世区块记录seq在不同主链节点上差异很大,通过记录的主链hash获取的真实seq-1来使用,主链hash使用对应区块的parenthash做校验目的
func (client *client) getLastBlockMainInfo() (int64, []byte, error) {
lastSeq, lastBlock, err := client.getLastBlockInfo()
if err != nil {
return -2, nil, err
}
if lastBlock.Height == 0 && lastSeq > -1 {
mainBlock, err := client.GetBlockOnMainByHash(lastBlock.MainHash)
if err != nil {
return -2, nil, err
}
mainSeq, err := client.GetSeqByHashOnMainChain(lastBlock.MainHash)
if err != nil {
return -2, nil, err
}
return mainSeq - 1, mainBlock.ParentHash, nil
}
return lastSeq, lastBlock.MainHash, nil
}
func (client *client) getLastBlockInfo() (int64, *types.Block, error) {
lastBlock, err := client.RequestLastBlock()
if err != nil {
......@@ -317,22 +343,6 @@ func (client *client) getLastBlockInfo() (int64, *types.Block, error) {
plog.Error("Parachain GetBlockedSeq fail", "err", err)
return -2, nil, err
}
// 平行链创世区块特殊场景:
// 1,创世区块seq从-1开始,也就是从主链0高度同步区块,主链seq从0开始,平行链对seq=0的区块做特殊处理,不校验parentHash
// 2,创世区块seq不是-1, 也就是从主链seq=n高度同步区块,此时创世区块倒退一个seq,blockedSeq=n-1,
// 由于创世区块本身没有记录主块hash,需要通过最初记录的seq获取,有可能n-1 seq 是回退block 获取的Hash不对,这里获取主链第n seq的parentHash
// 在genesis create时候直接设mainhash也可以,但是会导致已有平行链所有block hash变化
if lastBlock.Height == 0 && blockedSeq > -1 {
main, err := client.GetBlockOnMainBySeq(blockedSeq + 1)
if err != nil {
return -2, nil, err
}
lastBlock.MainHash = main.Detail.Block.ParentHash
lastBlock.MainHeight = main.Detail.Block.Height - 1
return blockedSeq, lastBlock, nil
}
return blockedSeq, lastBlock, nil
}
......@@ -365,13 +375,13 @@ func (client *client) GetLastSeqOnMainChain() (int64, error) {
return seq.Data, nil
}
func (client *client) GetSeqByHeightOnMainChain(height int64) (int64, error) {
func (client *client) GetSeqByHeightOnMainChain(height int64) (int64, []byte, error) {
hash, err := client.GetHashByHeightOnMainChain(height)
if err != nil {
return -1, err
return -1, nil, err
}
seq, err := client.GetSeqByHashOnMainChain(hash)
return seq, err
return seq, hash, err
}
func (client *client) GetHashByHeightOnMainChain(height int64) ([]byte, error) {
......@@ -410,6 +420,16 @@ func (client *client) GetBlockOnMainBySeq(seq int64) (*types.BlockSeq, error) {
return blockSeq, nil
}
func (client *client) GetBlockOnMainByHash(hash []byte) (*types.Block, error) {
blocks, err := client.grpcClient.GetBlockByHashes(context.Background(), &types.ReqHashes{Hashes: [][]byte{hash}})
if err != nil || blocks.Items[0] == nil {
plog.Error("GetBlockOnMainByHash Not found", "blockhash", common.ToHex(hash))
return nil, err
}
return blocks.Items[0].Block, nil
}
// preBlockHash to identify the same main node
func (client *client) RequestTx(currSeq int64, preMainBlockHash []byte) ([]*types.Transaction, *types.BlockSeq, error) {
plog.Debug("Para consensus RequestTx")
......@@ -466,13 +486,13 @@ func (client *client) RequestTx(currSeq int64, preMainBlockHash []byte) ([]*type
// for genesis seq=-1 scenario, mainHash not care, as the 0 seq instead of -1
// not seq=-1 scenario, mainHash needed
func (client *client) syncFromGenesisBlock() (int64, []byte, error) {
lastSeq, lastBlock, err := client.getLastBlockInfo()
lastSeq, lastMainHash, err := client.getLastBlockMainInfo()
if err != nil {
plog.Error("Parachain getLastBlockInfo fail", "err", err)
return -2, nil, err
}
plog.Info("syncFromGenesisBlock sync from height 0")
return lastSeq + 1, lastBlock.MainHash, nil
return lastSeq + 1, lastMainHash, nil
}
// search base on para block but not last MainBlockHash, last MainBlockHash can not back tracing
......@@ -561,12 +581,11 @@ func (client *client) removeBlocks(endHeight int64) error {
func (client *client) CreateBlock() {
incSeqFlag := true
//system startup, take the last added block's seq is ok
currSeq, lastBlock, err := client.getLastBlockInfo()
currSeq, lastSeqMainHash, err := client.getLastBlockMainInfo()
if err != nil {
plog.Error("Parachain getLastBlockInfo fail", "err", err.Error())
return
}
lastSeqMainHash := lastBlock.MainHash
for {
//should be lastSeq but not LastBlockSeq as del block case the seq is not equal
lastSeq, err := client.GetLastSeq()
......@@ -660,15 +679,6 @@ func (client *client) addMinerTx(preStateHash []byte, block *types.Block, main *
MainBlockHeight: main.Detail.Block.Height,
}
//获取当前区块的所有原始tx hash 和跨链hash作为bitmap base hashs,因为有可能在执行过程中有些tx 执行error被剔除掉
if main.Detail.Block.Height >= mainForkParacrossCommitTx {
for _, tx := range txs {
status.TxHashs = append(status.TxHashs, tx.Hash())
}
txHashs := paraexec.FilterParaCrossTxHashes(types.GetTitle(), txs)
status.CrossTxHashs = append(status.CrossTxHashs, txHashs...)
}
tx, err := pt.CreateRawMinerTx(&pt.ParacrossMinerAction{
Status: status,
IsSelfConsensus: isParaSelfConsensusForked(status.MainBlockHeight),
......
......@@ -13,8 +13,12 @@ import (
"testing"
"time"
apimocks "github.com/33cn/chain33/client/mocks"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/queue"
qmocks "github.com/33cn/chain33/queue/mocks"
drivers "github.com/33cn/chain33/system/consensus"
"github.com/33cn/chain33/types"
typesmocks "github.com/33cn/chain33/types/mocks"
paraexec "github.com/33cn/plugin/plugin/dapp/paracross/executor"
......@@ -220,3 +224,43 @@ func TestAddMinerTx(t *testing.T) {
assert.False(t, ret)
}
func initBlock() {
println("initblock")
}
func TestGetLastBlockInfo(t *testing.T) {
para := new(client)
baseCli := drivers.NewBaseClient(&types.Consensus{Name: "name"})
para.BaseClient = baseCli
grpcClient := &typesmocks.Chain33Client{}
qClient := &qmocks.Client{}
para.InitClient(qClient, initBlock)
api := &apimocks.QueueProtocolAPI{}
para.SetAPI(api)
para.grpcClient = grpcClient
block := &types.Block{Height: 0}
msg := queue.NewMessage(0, "", 1, block)
qClient.On("NewMessage", mock.Anything, mock.Anything, mock.Anything).Return(msg)
qClient.On("Send", mock.Anything, mock.Anything).Return(nil)
qClient.On("Wait", mock.Anything).Return(msg, nil)
api.On("GetSequenceByHash", mock.Anything).Return(&types.Int64{Data: int64(1)}, nil)
mainBlock := &types.Block{ParentHash: []byte("phash")}
mainDetail := &types.BlockDetail{Block: mainBlock}
blocks := &types.BlockDetails{}
blocks.Items = append(blocks.Items, mainDetail)
grpcClient.On("GetBlockByHashes", mock.Anything, mock.Anything).Return(blocks, nil)
grpcClient.On("GetSequenceByHash", mock.Anything, mock.Anything).Return(&types.Int64{Data: int64(10)}, nil)
mainSeq, hash, err := para.getLastBlockMainInfo()
assert.NoError(t, err)
assert.Equal(t, int64(9), mainSeq)
assert.Equal(t, []byte("phash"), hash)
}
#!/usr/bin/env bash
# shellcheck disable=SC2128
set -e
set +e
set -o pipefail
set -x
MAIN_HTTP=""
CASE_ERR=""
......
all:
chmod +x ./build.sh
./build.sh $(OUT) $(FLAG)
\ No newline at end of file
#!/usr/bin/env bash
strpwd=$(pwd)
strcmd=${strpwd##*dapp/}
strapp=${strcmd%/cmd*}
OUT_DIR="${1}/$strapp"
#FLAG=$2
mkdir -p "${OUT_DIR}"
cp ./build/* "${OUT_DIR}"
OUT_TESTDIR="${1}/dapptest/$strapp"
mkdir -p "${OUT_TESTDIR}"
chmod +x ./build/test-rpc.sh
cp ./build/test-rpc.sh "${OUT_TESTDIR}"
This diff is collapsed.
......@@ -8,6 +8,7 @@ import (
"github.com/33cn/chain33/pluginmgr"
"github.com/33cn/plugin/plugin/dapp/evm/commands"
"github.com/33cn/plugin/plugin/dapp/evm/executor"
"github.com/33cn/plugin/plugin/dapp/evm/rpc"
"github.com/33cn/plugin/plugin/dapp/evm/types"
)
......@@ -17,6 +18,6 @@ func init() {
ExecName: executor.GetName(),
Exec: executor.Init,
Cmd: commands.EvmCmd,
RPC: nil,
RPC: rpc.Init,
})
}
......@@ -146,4 +146,36 @@ message EvmQueryResp {
string caller = 3;
string rawData = 4;
string jsonData = 5;
}
message EvmContractCreateReq {
string code = 1;
int64 fee = 2;
string note = 3;
string alias = 4;
string caller = 5;
string abi = 6;
string expire = 7;
string paraName = 8;
}
message EvmContractCallReq {
uint64 amount = 1;
string code = 2;
int64 fee = 3;
string note = 4;
string caller = 5;
string abi = 6;
string exec = 7;
string expire = 8;
string paraName = 9;
}
message EvmContractTransferReq {
string caller = 1;
float amount = 2;
string exec = 3;
string expire = 4;
bool isWithdraw = 5;
string paraName = 6;
}
\ No newline at end of file
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package rpc
import (
"context"
"encoding/hex"
"github.com/33cn/chain33/types"
evm "github.com/33cn/plugin/plugin/dapp/evm/types"
)
// EvmCreateTx 创建Evm合约接口
func (c *Jrpc) EvmCreateTx(parm *evm.EvmContractCreateReq, result *interface{}) error {
if parm == nil {
return types.ErrInvalidParam
}
reply, err := c.cli.Create(context.Background(), *parm)
if err != nil {
return err
}
*result = hex.EncodeToString(reply.Data)
return nil
}
// EvmCallTx 调用Evm合约接口
func (c *Jrpc) EvmCallTx(parm *evm.EvmContractCallReq, result *interface{}) error {
if parm == nil {
return types.ErrInvalidParam
}
reply, err := c.cli.Call(context.Background(), *parm)
if err != nil {
return err
}
*result = hex.EncodeToString(reply.Data)
return nil
}
// EvmTransferTx Evm转账接口
func (c *Jrpc) EvmTransferTx(parm *evm.EvmContractTransferReq, result *interface{}) error {
if parm == nil {
return types.ErrInvalidParam
}
reply, err := c.cli.Transfer(context.Background(), *parm, false)
if err != nil {
return err
}
*result = hex.EncodeToString(reply.Data)
return nil
}
// EvmWithdrawTx Evm转账接口
func (c *Jrpc) EvmWithdrawTx(parm *evm.EvmContractTransferReq, result *interface{}) error {
if parm == nil {
return types.ErrInvalidParam
}
reply, err := c.cli.Transfer(context.Background(), *parm, true)
if err != nil {
return err
}
*result = hex.EncodeToString(reply.Data)
return nil
}
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package rpc
import (
"context"
"fmt"
"math/rand"
"os"
"time"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/address"
cty "github.com/33cn/chain33/system/dapp/coins/types"
"github.com/33cn/chain33/types"
evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types"
)
// CreateEvmCallTx 创建未签名的调用evm交易
func (c *channelClient) Create(ctx context.Context, in evmtypes.EvmContractCreateReq) (*types.UnsignTx, error) {
bCode, err := common.FromHex(in.Code)
if err != nil {
fmt.Fprintln(os.Stderr, "parse evm code error", err)
return nil, err
}
action := evmtypes.EVMContractAction{Amount: 0, Code: bCode, GasLimit: 0, GasPrice: 0, Note: in.Note, Abi: in.Abi}
execer := types.ExecName(in.ParaName + "evm")
addr := address.ExecAddress(types.ExecName(in.ParaName + "evm"))
tx := &types.Transaction{Execer: []byte(execer), Payload: types.Encode(&action), Fee: 0, To: addr}
tx.Fee, _ = tx.GetRealFee(types.GInt("MinFee"))
if tx.Fee < in.Fee {
tx.Fee += in.Fee
}
random := rand.New(rand.NewSource(time.Now().UnixNano()))
tx.Nonce = random.Int63()
txHex := types.Encode(tx)
return &types.UnsignTx{Data: txHex}, nil
}
func (c *channelClient) Call(ctx context.Context, in evmtypes.EvmContractCallReq) (*types.UnsignTx, error) {
amountInt64 := in.Amount * 1e4 * 1e4
feeInt64 := in.Fee * 1e4 * 1e4
toAddr := address.ExecAddress(in.Exec)
bCode, err := common.FromHex(in.Code)
if err != nil {
fmt.Fprintln(os.Stderr, "parse evm code error", err)
return nil, err
}
action := evmtypes.EVMContractAction{Amount: amountInt64, Code: bCode, GasLimit: 0, GasPrice: 0, Note: in.Note, Abi: in.Abi}
tx := &types.Transaction{Execer: []byte(in.Exec), Payload: types.Encode(&action), Fee: 0, To: toAddr}
tx.Fee, _ = tx.GetRealFee(types.GInt("MinFee"))
if tx.Fee < feeInt64 {
tx.Fee += feeInt64
}
random := rand.New(rand.NewSource(time.Now().UnixNano()))
tx.Nonce = random.Int63()
txHex := types.Encode(tx)
return &types.UnsignTx{Data: txHex}, nil
}
func (c *channelClient) Transfer(ctx context.Context, in evmtypes.EvmContractTransferReq, isWithdraw bool) (*types.UnsignTx, error) {
var tx *types.Transaction
transfer := &cty.CoinsAction{}
amountInt64 := int64(in.Amount*1e4) * 1e4
execName := in.Exec
if isWithdraw {
transfer.Value = &cty.CoinsAction_Withdraw{Withdraw: &types.AssetsWithdraw{Amount: amountInt64, ExecName: execName, To: address.ExecAddress(execName)}}
transfer.Ty = cty.CoinsActionWithdraw
} else {
transfer.Value = &cty.CoinsAction_TransferToExec{TransferToExec: &types.AssetsTransferToExec{Amount: amountInt64, ExecName: execName, To: address.ExecAddress(execName)}}
transfer.Ty = cty.CoinsActionTransferToExec
}
if in.ParaName == "" {
tx = &types.Transaction{Execer: []byte(types.ExecName(in.ParaName + "coins")), Payload: types.Encode(transfer), To: address.ExecAddress(execName)}
} else {
tx = &types.Transaction{Execer: []byte(types.ExecName(in.ParaName + "coins")), Payload: types.Encode(transfer), To: address.ExecAddress(types.ExecName(in.ParaName + "coins"))}
}
var err error
tx.Fee, err = tx.GetRealFee(types.GInt("MinFee"))
if err != nil {
return nil, err
}
random := rand.New(rand.NewSource(time.Now().UnixNano()))
tx.Nonce = random.Int63()
txHex := types.Encode(tx)
return &types.UnsignTx{Data: txHex}, nil
}
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package rpc
import (
"github.com/33cn/chain33/rpc/types"
)
// Jrpc json rpc struct
type Jrpc struct {
cli *channelClient
}
// Grpc grpc struct
type Grpc struct {
*channelClient
}
type channelClient struct {
types.ChannelClient
}
// Init init grpc param
func Init(name string, s types.RPCServer) {
cli := &channelClient{}
grpc := &Grpc{channelClient: cli}
cli.Init(name, s, &Jrpc{cli: cli}, grpc)
}
This diff is collapsed.
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
This diff is collapsed.
......@@ -5,6 +5,8 @@
package executor
import (
"bytes"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/util"
......@@ -125,22 +127,41 @@ func (e *Paracross) ExecLocal_AssetWithdraw(payload *types.AssetsWithdraw, tx *t
return nil, nil
}
func setMinerTxResult(payload *pt.ParacrossMinerAction, txs []*types.Transaction, receipts []*types.ReceiptData) {
var curTxHashs, paraTxHashs [][]byte
func setMinerTxResult(payload *pt.ParacrossMinerAction, txs []*types.Transaction, receipts []*types.ReceiptData) error {
isCommitTx := make(map[string]bool)
var curTxHashs, paraTxHashs, crossTxHashs [][]byte
for _, tx := range txs {
hash := tx.Hash()
curTxHashs = append(curTxHashs, hash)
//对user.p.xx.paracross ,actionTy==commit 的tx不需要再发回主链
if types.IsMyParaExecName(string(tx.Execer)) && bytes.HasSuffix(tx.Execer, []byte(pt.ParaX)) {
var payload pt.ParacrossAction
err := types.Decode(tx.Payload, &payload)
if err != nil {
clog.Error("setMinerTxResult", "txHash", common.ToHex(hash))
return err
}
if payload.Ty == pt.ParacrossActionCommit {
isCommitTx[string(hash)] = true
}
}
//跨链交易包含了主链交易,需要过滤出来
if types.IsMyParaExecName(string(tx.Execer)) {
if types.IsMyParaExecName(string(tx.Execer)) && !isCommitTx[string(hash)] {
paraTxHashs = append(paraTxHashs, hash)
}
}
crossTxHashs := FilterParaMainCrossTxHashes(types.GetTitle(), txs)
totalCrossTxHashs := FilterParaMainCrossTxHashes(types.GetTitle(), txs)
for _, crossHash := range totalCrossTxHashs {
if !isCommitTx[string(crossHash)] {
crossTxHashs = append(crossTxHashs, crossHash)
}
}
payload.Status.TxHashs = paraTxHashs
payload.Status.TxResult = util.CalcBitMap(paraTxHashs, curTxHashs, receipts)
payload.Status.CrossTxHashs = crossTxHashs
payload.Status.CrossTxResult = util.CalcBitMap(crossTxHashs, curTxHashs, receipts)
return nil
}
func setMinerTxResultFork(payload *pt.ParacrossMinerAction, txs []*types.Transaction, receipts []*types.ReceiptData) {
......@@ -149,16 +170,16 @@ func setMinerTxResultFork(payload *pt.ParacrossMinerAction, txs []*types.Transac
hash := tx.Hash()
curTxHashs = append(curTxHashs, hash)
}
baseTxHashs := payload.Status.TxHashs
baseCrossTxHashs := payload.Status.CrossTxHashs
baseCrossTxHashs := FilterParaCrossTxHashes(types.GetTitle(), txs)
//主链自己过滤平行链tx, 对平行链执行失败的tx主链无法识别,主链和平行链需要获取相同的最初的tx map
//全部平行链tx结果
payload.Status.TxResult = util.CalcBitMap(baseTxHashs, curTxHashs, receipts)
payload.Status.TxResult = util.CalcBitMap(curTxHashs, curTxHashs, receipts)
//跨链tx结果
payload.Status.CrossTxResult = util.CalcBitMap(baseCrossTxHashs, curTxHashs, receipts)
payload.Status.TxHashs = [][]byte{CalcTxHashsHash(baseTxHashs)}
payload.Status.TxHashs = [][]byte{CalcTxHashsHash(curTxHashs)}
payload.Status.CrossTxHashs = [][]byte{CalcTxHashsHash(baseCrossTxHashs)}
}
......@@ -177,7 +198,10 @@ func (e *Paracross) ExecLocal_Miner(payload *pt.ParacrossMinerAction, tx *types.
if payload.Status.MainBlockHeight >= forkHeight {
setMinerTxResultFork(payload, txs[1:], e.GetReceipt()[1:])
} else {
setMinerTxResult(payload, txs[1:], e.GetReceipt()[1:])
err := setMinerTxResult(payload, txs[1:], e.GetReceipt()[1:])
if err != nil {
return nil, err
}
}
set.KV = append(set.KV, &types.KeyValue{
......
......@@ -488,10 +488,14 @@ func (s *VoteTestSuite) TestVoteTx() {
tx7, err := createAssetTransferTx(s.Suite, PrivKeyC, nil)
s.Nil(err)
tx8, err := createCrossCommitTx(s.Suite)
s.Nil(err)
txs := []*types.Transaction{tx, tx1, tx2}
txs = append(txs, txGroup34...)
txs = append(txs, txGroup56...)
txs = append(txs, tx7)
txs = append(txs, tx8)
s.exec.SetTxs(txs)
//for i,tx := range txs{
......@@ -508,7 +512,8 @@ func (s *VoteTestSuite) TestVoteTx() {
recpt5 := &types.ReceiptData{Ty: types.ExecPack}
recpt6 := &types.ReceiptData{Ty: types.ExecPack}
recpt7 := &types.ReceiptData{Ty: types.ExecOk}
receipts := []*types.ReceiptData{recpt0, recpt1, recpt2, recpt3, recpt4, recpt5, recpt6, recpt7}
recpt8 := &types.ReceiptData{Ty: types.ExecOk}
receipts := []*types.ReceiptData{recpt0, recpt1, recpt2, recpt3, recpt4, recpt5, recpt6, recpt7, recpt8}
s.exec.SetReceipt(receipts)
set, err := s.exec.ExecLocal(tx, recpt0, 0)
s.Nil(err)
......@@ -697,6 +702,24 @@ func createCrossParaTx(s suite.Suite, to []byte) (*types.Transaction, error) {
return tx, nil
}
func createCrossCommitTx(s suite.Suite) (*types.Transaction, error) {
status := &pt.ParacrossNodeStatus{MainBlockHash: []byte("hash"), MainBlockHeight: 0, Title: Title}
tx, err := pt.CreateRawCommitTx4MainChain(status, Title+pt.ParaX, 0)
assert.Nil(s.T(), err, "create asset transfer failed")
if err != nil {
return nil, err
}
//tx, err = signTx(s, tx, privFrom)
//assert.Nil(s.T(), err, "sign asset transfer failed")
//if err != nil {
// return nil, err
//}
return tx, nil
}
func createTxsGroup(s suite.Suite, txs []*types.Transaction) ([]*types.Transaction, error) {
group, err := types.CreateTxGroup(txs)
if err != nil {
......
......@@ -165,7 +165,7 @@ func (a *action) nodeJoin(config *pt.ParaNodeAddrConfig) (*types.Receipt, error)
receipt := &types.Receipt{Ty: types.ExecOk}
if !types.IsPara() {
r, err := a.nodeGroupCoinsFrozen([]string{a.fromaddr}, config.CoinsFrozen)
r, err := a.nodeGroupCoinsFrozen(a.fromaddr, config.CoinsFrozen, 1)
if err != nil {
return nil, err
}
......@@ -258,7 +258,7 @@ func (a *action) nodeQuit(config *pt.ParaNodeAddrConfig) (*types.Receipt, error)
//still adding status, quit directly
receipt := &types.Receipt{Ty: types.ExecOk}
if !types.IsPara() {
r, err := a.nodeGroupCoinsActive([]string{stat.FromAddr}, stat.CoinsFrozen)
r, err := a.nodeGroupCoinsActive(stat.FromAddr, stat.CoinsFrozen, 1)
if err != nil {
return nil, err
}
......@@ -438,7 +438,7 @@ func (a *action) nodeVote(config *pt.ParaNodeAddrConfig) (*types.Receipt, error)
stat.Status = pt.ParacrossNodeQuited
if !types.IsPara() {
r, err := a.nodeGroupCoinsActive([]string{stat.FromAddr}, stat.CoinsFrozen)
r, err := a.nodeGroupCoinsActive(stat.FromAddr, stat.CoinsFrozen, 1)
if err != nil {
return nil, err
}
......@@ -546,40 +546,35 @@ func (a *action) checkNodeGroupExist(title string) error {
return nil
}
func (a *action) nodeGroupCoinsFrozen(addrs []string, configCoinsFrozen int64) (*types.Receipt, error) {
func (a *action) nodeGroupCoinsFrozen(createAddr string, configCoinsFrozen int64, nodeCounts int64) (*types.Receipt, error) {
receipt := &types.Receipt{}
confCoins := conf.GInt("nodeGroupFrozenCoins")
if configCoinsFrozen < confCoins {
return nil, pt.ErrParaNodeGroupFrozenCoinsNotEnough
}
if configCoinsFrozen == 0 {
clog.Info("node group apply configCoinsFrozen is 0")
return receipt, nil
}
var logs []*types.ReceiptLog
var kv []*types.KeyValue
realExec := string(types.GetRealExecName(a.tx.Execer))
realExecAddr := dapp.ExecAddress(realExec)
for _, addr := range addrs {
r, err := a.coinsAccount.ExecFrozen(addr, realExecAddr, configCoinsFrozen)
if err != nil {
clog.Error("node group apply", "addr", addr, "realExec", realExec, "realAddr", realExecAddr, "amount", configCoinsFrozen)
return nil, err
}
logs = append(logs, r.Logs...)
kv = append(kv, r.KV...)
r, err := a.coinsAccount.ExecFrozen(createAddr, realExecAddr, nodeCounts*configCoinsFrozen)
if err != nil {
clog.Error("node group apply", "addr", createAddr, "realExec", realExec, "realAddr", realExecAddr, "amount", configCoinsFrozen)
return nil, err
}
receipt.KV = append(receipt.KV, kv...)
receipt.Logs = append(receipt.Logs, logs...)
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
return receipt, nil
}
func (a *action) nodeGroupCoinsActive(addrs []string, configCoinsFrozen int64) (*types.Receipt, error) {
func (a *action) nodeGroupCoinsActive(createAddr string, configCoinsFrozen int64, nodeCount int64) (*types.Receipt, error) {
receipt := &types.Receipt{}
var logs []*types.ReceiptLog
var kv []*types.KeyValue
realExec := string(types.GetRealExecName(a.tx.Execer))
realExecAddr := dapp.ExecAddress(realExec)
......@@ -587,17 +582,15 @@ func (a *action) nodeGroupCoinsActive(addrs []string, configCoinsFrozen int64) (
return receipt, nil
}
for _, addr := range addrs {
r, err := a.coinsAccount.ExecActive(addr, realExecAddr, configCoinsFrozen)
if err != nil {
clog.Error("node group apply", "addr", addr, "realExec", realExec, "realAddr", realExecAddr, "amount", configCoinsFrozen)
return nil, err
}
logs = append(logs, r.Logs...)
kv = append(kv, r.KV...)
r, err := a.coinsAccount.ExecActive(createAddr, realExecAddr, nodeCount*configCoinsFrozen)
if err != nil {
clog.Error("node group apply", "addr", createAddr,
"realExec", realExec, "realAddr", realExecAddr, "amount", configCoinsFrozen, "nodeCount", nodeCount)
return nil, err
}
receipt.KV = append(receipt.KV, kv...)
receipt.Logs = append(receipt.Logs, logs...)
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
return receipt, nil
}
......@@ -617,7 +610,7 @@ func (a *action) nodeGroupApply(config *pt.ParaNodeGroupConfig) (*types.Receipt,
receipt := &types.Receipt{Ty: types.ExecOk}
//main chain
if !types.IsPara() {
r, err := a.nodeGroupCoinsFrozen(addrs, config.CoinsFrozen)
r, err := a.nodeGroupCoinsFrozen(a.fromaddr, config.CoinsFrozen, int64(len(addrs)))
if err != nil {
return nil, err
}
......@@ -631,7 +624,8 @@ func (a *action) nodeGroupApply(config *pt.ParaNodeGroupConfig) (*types.Receipt,
ApplyAddr: strings.Join(addrs, ","),
CoinsFrozen: config.CoinsFrozen,
MainHeight: a.exec.GetMainHeight(),
EmptyBlockInterval: config.EmptyBlockInterval}
EmptyBlockInterval: config.EmptyBlockInterval,
FromAddr: a.fromaddr}
saveNodeGroup(a.db, config.Title, stat)
r := makeParaNodeGroupApplyReiceipt(config.Title, a.fromaddr, status, stat, pt.TyLogParaNodeGroupApply)
receipt.KV = append(receipt.KV, r.KV...)
......@@ -650,6 +644,11 @@ func (a *action) nodeGroupQuit(config *pt.ParaNodeGroupConfig) (*types.Receipt,
return nil, pt.ErrParaNodeGroupStatusWrong
}
if status.FromAddr != a.fromaddr {
clog.Error("node group create addr err", "createAddr", status.FromAddr, "currAddr", a.fromaddr)
return nil, types.ErrNotAllow
}
applyAddrs, err := checkNodeGroupAddrsMatch(status.ApplyAddr, config.Addrs)
if err != nil {
return nil, err
......@@ -658,7 +657,7 @@ func (a *action) nodeGroupQuit(config *pt.ParaNodeGroupConfig) (*types.Receipt,
receipt := &types.Receipt{Ty: types.ExecOk}
//main chain
if !types.IsPara() {
r, err := a.nodeGroupCoinsActive(applyAddrs, status.CoinsFrozen)
r, err := a.nodeGroupCoinsActive(a.fromaddr, status.CoinsFrozen, int64(len(applyAddrs)))
if err != nil {
return nil, err
}
......@@ -671,7 +670,8 @@ func (a *action) nodeGroupQuit(config *pt.ParaNodeGroupConfig) (*types.Receipt,
ApplyAddr: status.ApplyAddr,
CoinsFrozen: status.CoinsFrozen,
MainHeight: a.exec.GetMainHeight(),
EmptyBlockInterval: status.EmptyBlockInterval}
EmptyBlockInterval: status.EmptyBlockInterval,
FromAddr: a.fromaddr}
saveNodeGroup(a.db, config.Title, stat)
r := makeParaNodeGroupApplyReiceipt(config.Title, a.fromaddr, status, stat, pt.TyLogParaNodeGroupQuit)
receipt.KV = append(receipt.KV, r.KV...)
......@@ -734,7 +734,7 @@ func (a *action) nodeGroupApprove(config *pt.ParaNodeGroupConfig) (*types.Receip
receipt := &types.Receipt{Ty: types.ExecOk}
//create the node group
r, err := a.nodeGroupCreate(config.Title, applyAddrs, config.CoinsFrozen)
r, err := a.nodeGroupCreate(config.Title, applyAddrs, status.CoinsFrozen, status.FromAddr)
if err != nil {
return nil, err
}
......@@ -746,7 +746,8 @@ func (a *action) nodeGroupApprove(config *pt.ParaNodeGroupConfig) (*types.Receip
ApplyAddr: status.ApplyAddr,
CoinsFrozen: status.CoinsFrozen,
MainHeight: a.exec.GetMainHeight(),
EmptyBlockInterval: status.EmptyBlockInterval}
EmptyBlockInterval: status.EmptyBlockInterval,
FromAddr: status.FromAddr}
saveNodeGroup(a.db, config.Title, stat)
r = makeParaNodeGroupApplyReiceipt(config.Title, a.fromaddr, status, stat, pt.TyLogParaNodeGroupApprove)
receipt.KV = append(receipt.KV, r.KV...)
......@@ -755,7 +756,7 @@ func (a *action) nodeGroupApprove(config *pt.ParaNodeGroupConfig) (*types.Receip
return receipt, nil
}
func (a *action) nodeGroupCreate(title string, nodes []string, coinFrozen int64) (*types.Receipt, error) {
func (a *action) nodeGroupCreate(title string, nodes []string, coinFrozen int64, createAddr string) (*types.Receipt, error) {
var item types.ConfigItem
key := calcParaNodeGroupKey(title)
item.Key = string(key)
......@@ -774,7 +775,8 @@ func (a *action) nodeGroupCreate(title string, nodes []string, coinFrozen int64)
Title: title,
ApplyAddr: addr,
Votes: &pt.ParaNodeVoteDetail{},
CoinsFrozen: coinFrozen}
CoinsFrozen: coinFrozen,
FromAddr: createAddr}
saveNodeAddr(a.db, title, addr, stat)
config := &pt.ParaNodeAddrConfig{
Title: title,
......@@ -799,10 +801,6 @@ func (a *action) NodeGroupConfig(config *pt.ParaNodeGroupConfig) (*types.Receipt
}
if config.Op == pt.ParacrossNodeGroupApply {
if !strings.Contains(config.Addrs, a.fromaddr) {
clog.Error("node group apply fromaddr not one of apply addrs", "addr", a.fromaddr, "apply", config.Addrs)
return nil, types.ErrNotAllow
}
err := a.checkNodeGroupExist(config.Title)
if err != nil {
return nil, err
......@@ -817,10 +815,6 @@ func (a *action) NodeGroupConfig(config *pt.ParaNodeGroupConfig) (*types.Receipt
return a.nodeGroupApprove(config)
} else if config.Op == pt.ParacrossNodeGroupQuit {
if !strings.Contains(config.Addrs, a.fromaddr) {
clog.Error("node group apply fromaddr not one of apply addrs", "addr", a.fromaddr, "apply", config.Addrs)
return nil, types.ErrNotAllow
}
return a.nodeGroupQuit(config)
}
......
......@@ -99,6 +99,7 @@ message ParaNodeGroupStatus {
int64 coinsFrozen = 4;
uint32 emptyBlockInterval = 5;
int64 mainHeight = 6;
string fromAddr = 7;
}
message ReceiptParaNodeGroupConfig {
......
This diff is collapsed.
......@@ -26,7 +26,7 @@ func init() {
types.RegistorExecutor(ParaX, NewType())
types.RegisterDappFork(ParaX, "Enable", 0)
types.RegisterDappFork(ParaX, "ForkParacrossWithdrawFromParachain", 1298600)
types.RegisterDappFork(ParaX, ForkCommitTx, types.MaxHeight)
types.RegisterDappFork(ParaX, ForkCommitTx, 1850000)
}
// GetExecName get para exec name
......
......@@ -202,6 +202,7 @@ ForkStateDBSet=-1 #fork 6.2
ForkLocalDBAccess=-1 #fork 6.2
ForkBlockCheck=-1 #fork 6.2
ForkBase58AddressCheck=-1 #fork6.2
ForkEnableParaRegExec=0
[fork.sub.coins]
Enable=0
[fork.sub.ticket]
......
......@@ -108,11 +108,11 @@ func (t *token) getAccountTokenAssets(req *tokenty.ReqAccountTokenAssets) (types
return nil, err
}
var acc1 *types.Account
if req.Execer != "" {
execaddress := address.ExecAddress(req.Execer)
acc1 = acc.LoadExecAccount(req.Address, execaddress)
} else if req.Execer == t.GetName() {
if req.Execer == t.GetName() {
acc1 = acc.LoadAccount(req.Address)
} else if req.Execer != "" {
execAddress := address.ExecAddress(req.Execer)
acc1 = acc.LoadExecAccount(req.Address, execAddress)
}
if acc1 == nil {
continue
......
......@@ -152,6 +152,9 @@ func TestToken(t *testing.T) {
set, err := exec.ExecLocal(createTx, receiptDate, int(1))
assert.Nil(t, err)
assert.NotNil(t, set)
for _, kv := range set.KV {
kvdb.Set(kv.Key, kv.Value)
}
p2 := &pty.TokenFinishCreate{
Symbol: Symbol,
......@@ -176,13 +179,16 @@ func TestToken(t *testing.T) {
stateDB.Set(kv.Key, kv.Value)
}
accDB, _ := account.NewAccountDB(pty.TokenX, Symbol, stateDB)
accChcek := accDB.LoadAccount(string(Nodes[0]))
assert.Equal(t, tokenTotal, accChcek.Balance)
accCheck := accDB.LoadAccount(string(Nodes[0]))
assert.Equal(t, tokenTotal, accCheck.Balance)
receiptDate = &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err = exec.ExecLocal(createTx2, receiptDate, int(1))
assert.Nil(t, err)
assert.NotNil(t, set)
for _, kv := range set.KV {
kvdb.Set(kv.Key, kv.Value)
}
// mint burn
p3 := &pty.TokenMint{
......@@ -208,13 +214,16 @@ func TestToken(t *testing.T) {
stateDB.Set(kv.Key, kv.Value)
}
accChcek = accDB.LoadAccount(string(Nodes[0]))
assert.Equal(t, tokenTotal+tokenMint, accChcek.Balance)
accCheck = accDB.LoadAccount(string(Nodes[0]))
assert.Equal(t, tokenTotal+tokenMint, accCheck.Balance)
receiptDate = &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err = exec.ExecLocal(createTx3, receiptDate, int(1))
assert.Nil(t, err)
assert.NotNil(t, set)
for _, kv := range set.KV {
kvdb.Set(kv.Key, kv.Value)
}
p4 := &pty.TokenBurn{
Symbol: Symbol,
......@@ -238,13 +247,31 @@ func TestToken(t *testing.T) {
for _, kv := range receipt.KV {
stateDB.Set(kv.Key, kv.Value)
}
accChcek = accDB.LoadAccount(string(Nodes[0]))
assert.Equal(t, tokenTotal+tokenMint-tokenBurn, accChcek.Balance)
accCheck = accDB.LoadAccount(string(Nodes[0]))
assert.Equal(t, tokenTotal+tokenMint-tokenBurn, accCheck.Balance)
receiptDate = &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err = exec.ExecLocal(createTx4, receiptDate, int(1))
assert.Nil(t, err)
assert.NotNil(t, set)
for _, kv := range set.KV {
kvdb.Set(kv.Key, kv.Value)
}
tokenExec, ok := exec.(*token)
assert.True(t, ok)
in := pty.ReqAccountTokenAssets{
Address: string(Nodes[0]),
Execer: pty.TokenX,
}
out, err := tokenExec.Query_GetAccountTokenAssets(&in)
assert.Nil(t, err)
reply := out.(*pty.ReplyAccountTokenAssets)
assert.Equal(t, 1, len(reply.TokenAssets))
assert.NotEqual(t, 0, reply.TokenAssets[0].Account.Balance)
assert.Equal(t, string(Nodes[0]), reply.TokenAssets[0].Account.Addr)
t.Log(reply.TokenAssets)
}
func signTx(tx *types.Transaction, hexPrivKey string) (*types.Transaction, error) {
......
......@@ -61,7 +61,7 @@ func DisableLog() {
func init() {
drivers.Reg("kvmvccmavl", New)
types.RegisterDappFork("store-kvmvccmavl", "ForkKvmvccmavl", types.MaxHeight)
types.RegisterDappFork("store-kvmvccmavl", "ForkKvmvccmavl", 186*10000)
}
// KVmMavlStore provide kvmvcc and mavl store interface implementation
......
......@@ -129,12 +129,8 @@ func (m *mockBlockChain) SetQueueClient(q queue.Queue) {
msg.ReplyErr("Do not support", types.ErrInvalidParam)
}
case types.EventLocalList:
if req, ok := msg.GetData().(*types.LocalDBList); ok {
if len(req.Key) > 0 && bytes.Equal(req.Key, []byte("Statistics:TicketInfoOrder:Addr:case1")) {
msg.Reply(client.NewMessage(blockchainKey, types.EventReplyQuery, &types.TicketMinerInfo{}))
} else {
msg.Reply(client.NewMessage(blockchainKey, types.EventReplyQuery, &types.LocalReplyValue{}))
}
if _, ok := msg.GetData().(*types.LocalDBList); ok {
msg.Reply(client.NewMessage(blockchainKey, types.EventReplyQuery, &types.LocalReplyValue{}))
} else {
msg.ReplyErr("Do not support", types.ErrInvalidParam)
}
......
......@@ -76,17 +76,15 @@ func (j *JSONRPCServer) Listen() (int, error) {
}
//格式做一个检查
client, err := parseJSONRpcParams(data)
errstr := "nil"
if err != nil {
errstr = err.Error()
err = fmt.Errorf(`invalid json request err:%s`, err.Error())
log.Debug("JSONRPCServer", "request", string(data), "parseErr", err)
writeError(w, r, 0, err.Error())
return
}
funcName := strings.Split(client.Method, ".")[len(strings.Split(client.Method, "."))-1]
if !checkFilterPrintFuncBlacklist(funcName) {
log.Debug("JSONRPCServer", "request", string(data), "err", errstr)
}
if err != nil {
writeError(w, r, 0, fmt.Sprintf(`parse request err %s`, err.Error()))
return
log.Debug("JSONRPCServer", "request", string(data))
}
//Release local request
ipaddr := net.ParseIP(ip)
......
......@@ -215,7 +215,7 @@ func createTxGroup(cmd *cobra.Command, args []string) {
fmt.Fprintln(os.Stderr, err)
return
}
err = group.Check(0, types.GInt("MinFee"), types.GInt("MaxFee"))
err = group.CheckWithFork(true, true, 0, types.GInt("MinFee"), types.GInt("MaxFee"))
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
......
......@@ -148,26 +148,6 @@ type GetTotalCoinsResult struct {
DifferenceAmount string `json:"differenceAmount,omitempty"`
}
// GetTicketStatisticResult defines ticketstatistic result rpc command
type GetTicketStatisticResult struct {
CurrentOpenCount int64 `json:"currentOpenCount"`
TotalMinerCount int64 `json:"totalMinerCount"`
TotalCloseCount int64 `json:"totalCloseCount"`
}
// GetTicketMinerInfoResult defines ticker minerinformation result rpc command
type GetTicketMinerInfoResult struct {
TicketID string `json:"ticketId"`
Status string `json:"status"`
PrevStatus string `json:"prevStatus"`
IsGenesis bool `json:"isGenesis"`
CreateTime string `json:"createTime"`
MinerTime string `json:"minerTime"`
CloseTime string `json:"closeTime"`
MinerValue int64 `json:"minerValue,omitempty"`
MinerAddress string `json:"minerAddress,omitempty"`
}
// UTXOGlobalIndex defines utxo globalindex command
type UTXOGlobalIndex struct {
// Height int64 `json:"height,omitempty"`
......
......@@ -35,20 +35,28 @@ func Register(name string, create DriverCreate, height int64) {
if _, dup := registedExecDriver[name]; dup {
panic("Execute: Register called twice for driver " + name)
}
driverWithHeight := &driverWithHeight{
driverHeight := &driverWithHeight{
create: create,
height: height,
}
registedExecDriver[name] = driverWithHeight
registedExecDriver[name] = driverHeight
//考虑到前期平行链兼容性和防止误操作(平行链下转账到一个主链合约),也会注册主链合约(不带前缀)的地址
registerAddress(name)
execDrivers[ExecAddress(name)] = driverHeight
if types.IsPara() {
paraHeight := types.GetFork("ForkEnableParaRegExec")
if paraHeight < height {
paraHeight = height
}
//平行链的合约地址是通过user.p.x.name计算的
paraDriverName := types.ExecName(name)
registerAddress(paraDriverName)
execDrivers[ExecAddress(paraDriverName)] = driverWithHeight
execDrivers[ExecAddress(paraDriverName)] = &driverWithHeight{
create: create,
height: paraHeight,
}
}
//考虑到前期平行链兼容性和防止误操作(平行链下转账到一个主链合约),也会注册主链合约(不带前缀)的地址
registerAddress(name)
execDrivers[ExecAddress(name)] = driverWithHeight
}
// LoadDriver load driver
......
......@@ -214,6 +214,8 @@ func SetTestNetFork() {
systemFork.SetFork("chain33", "ForkLocalDBAccess", 1572391)
systemFork.SetFork("chain33", "ForkTxGroupPara", 1687250)
systemFork.SetFork("chain33", "ForkBase58AddressCheck", 1800000)
//这个fork只影响平行链,注册类似user.p.x.exec的driver,新开的平行链设为0即可,老的平行链要设置新的高度
systemFork.SetFork("chain33", "ForkEnableParaRegExec", 0)
}
......
......@@ -34,33 +34,6 @@ message IterateRangeByStateHash {
int64 count = 4;
}
message TicketStatistic {
//当前在挖的ticket
int64 currentOpenCount = 1;
//一共挖到的ticket
int64 totalMinerCount = 2;
//一共取消的ticket
int64 totalCancleCount = 3;
}
message TicketMinerInfo {
string ticketId = 1;
// 1 -> 可挖矿 2 -> 已挖成功 3-> 已关闭
int32 status = 2;
int32 prevStatus = 3;
// genesis 创建的私钥比较特殊
bool isGenesis = 4;
//创建ticket时间
int64 createTime = 5;
// ticket挖矿时间
int64 minerTime = 6;
//关闭ticket时间
int64 closeTime = 7;
//挖到的币的数目
int64 minerValue = 8;
string minerAddress = 9;
}
message TotalAmount {
// 统计的总数
int64 total = 1;
......
......@@ -176,6 +176,7 @@ ForkMultiSignAddress=1298600
ForkBlockCheck=1725000
ForkLocalDBAccess=1
ForkBase58AddressCheck=1800000
ForkEnableParaRegExec=0
[fork.sub.coins]
Enable=0
......
......@@ -197,6 +197,7 @@ ForkMultiSignAddress=1298600
ForkBlockCheck=1
ForkLocalDBAccess=0
ForkBase58AddressCheck=1800000
ForkEnableParaRegExec=0
[fork.sub.coins]
Enable=0
......
......@@ -11,7 +11,7 @@ import (
"reflect"
"time"
"github.com/hashicorp/golang-lru"
lru "github.com/hashicorp/golang-lru"
"strconv"
......@@ -172,8 +172,8 @@ func (txgroup *Transactions) IsExpire(height, blocktime int64) bool {
return false
}
//Check height == 0 的时候,不做检查
func (txgroup *Transactions) Check(height, minfee, maxFee int64) error {
//CheckWithFork 和fork 无关的有个检查函数
func (txgroup *Transactions) CheckWithFork(checkFork, paraFork bool, height, minfee, maxFee int64) error {
txs := txgroup.Txs
if len(txs) < 2 {
return ErrTxGroupCountLessThanTwo
......@@ -193,7 +193,7 @@ func (txgroup *Transactions) Check(height, minfee, maxFee int64) error {
}
//txgroup 只允许一条平行链的交易, 且平行链txgroup须全部是平行链tx
//如果平行链已经在主链分叉高度前运行了一段时间且有跨链交易,平行链需要自己设置这个fork
if IsFork(height, "ForkTxGroupPara") {
if paraFork {
if len(para) > 1 {
tlog.Info("txgroup has multi para transaction")
return ErrTxGroupParaCount
......@@ -225,7 +225,7 @@ func (txgroup *Transactions) Check(height, minfee, maxFee int64) error {
if txs[0].Fee < totalfee {
return ErrTxFeeTooLow
}
if txs[0].Fee > maxFee && maxFee > 0 && IsFork(height, "ForkBlockCheck") {
if txs[0].Fee > maxFee && maxFee > 0 && checkFork {
return ErrTxFeeTooHigh
}
//检查hash是否符合要求
......@@ -261,6 +261,13 @@ func (txgroup *Transactions) Check(height, minfee, maxFee int64) error {
return nil
}
//Check height == 0 的时候,不做检查
func (txgroup *Transactions) Check(height, minfee, maxFee int64) error {
paraFork := IsFork(height, "ForkTxGroupPara")
checkFork := IsFork(height, "ForkBlockCheck")
return txgroup.CheckWithFork(checkFork, paraFork, height, minfee, maxFee)
}
//TransactionCache 交易缓存结构
type TransactionCache struct {
*Transaction
......
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