Commit 4ea2a651 authored by kingwang's avatar kingwang Committed by 33cn

update chain33 08/01

parent b8d027e4
...@@ -272,7 +272,7 @@ func (chain *BlockChain) InitBlockChain() { ...@@ -272,7 +272,7 @@ func (chain *BlockChain) InitBlockChain() {
} }
} }
types.S("dbversion", curdbver) types.S("dbversion", curdbver)
if !chain.cfg.IsParaChain { if !chain.cfg.IsParaChain && chain.cfg.RollbackBlock <= 0 {
// 定时检测/同步block // 定时检测/同步block
go chain.SynRoutine() go chain.SynRoutine()
......
...@@ -1109,7 +1109,7 @@ func testWriteBlockToDbTemp(t *testing.T, chain *blockchain.BlockChain) { ...@@ -1109,7 +1109,7 @@ func testWriteBlockToDbTemp(t *testing.T, chain *blockchain.BlockChain) {
rawblock.MainHeight = block.Block.MainHeight rawblock.MainHeight = block.Block.MainHeight
rawblock.Height = block.Block.Height + 1 rawblock.Height = block.Block.Height + 1
err = chain.WriteBlockToDbTemp(&rawblock) err = chain.WriteBlockToDbTemp(&rawblock, true)
if err != nil { if err != nil {
t.Error("testWriteBlockToDbTemp", "err", err) t.Error("testWriteBlockToDbTemp", "err", err)
} }
......
...@@ -206,7 +206,7 @@ func (chain *BlockChain) ReadBlockByHeight(height int64) (*types.Block, error) { ...@@ -206,7 +206,7 @@ func (chain *BlockChain) ReadBlockByHeight(height int64) (*types.Block, error) {
} }
//WriteBlockToDbTemp 快速下载的block临时存贮到数据库 //WriteBlockToDbTemp 快速下载的block临时存贮到数据库
func (chain *BlockChain) WriteBlockToDbTemp(block *types.Block) error { func (chain *BlockChain) WriteBlockToDbTemp(block *types.Block, lastHeightSave bool) error {
if block == nil { if block == nil {
panic("WriteBlockToDbTemp block is nil") panic("WriteBlockToDbTemp block is nil")
} }
...@@ -225,8 +225,10 @@ func (chain *BlockChain) WriteBlockToDbTemp(block *types.Block) error { ...@@ -225,8 +225,10 @@ func (chain *BlockChain) WriteBlockToDbTemp(block *types.Block) error {
chainlog.Error("WriteBlockToDbTemp:Marshal", "height", block.Height) chainlog.Error("WriteBlockToDbTemp:Marshal", "height", block.Height)
} }
newbatch.Set(calcHeightToTempBlockKey(block.Height), blockByte) newbatch.Set(calcHeightToTempBlockKey(block.Height), blockByte)
heightbytes := types.Encode(&types.Int64{Data: block.Height}) if lastHeightSave {
newbatch.Set(calcLastTempBlockHeightKey(), heightbytes) heightbytes := types.Encode(&types.Int64{Data: block.Height})
newbatch.Set(calcLastTempBlockHeightKey(), heightbytes)
}
return newbatch.Write() return newbatch.Write()
} }
......
...@@ -176,7 +176,7 @@ func (chain *BlockChain) addBlock(msg *queue.Message) { ...@@ -176,7 +176,7 @@ func (chain *BlockChain) addBlock(msg *queue.Message) {
blockpid := msg.Data.(*types.BlockPid) blockpid := msg.Data.(*types.BlockPid)
//chainlog.Error("addBlock", "height", blockpid.Block.Height, "pid", blockpid.Pid) //chainlog.Error("addBlock", "height", blockpid.Block.Height, "pid", blockpid.Pid)
if chain.GetDownloadSyncStatus() { if chain.GetDownloadSyncStatus() {
err := chain.WriteBlockToDbTemp(blockpid.Block) err := chain.WriteBlockToDbTemp(blockpid.Block, true)
if err != nil { if err != nil {
chainlog.Error("WriteBlockToDbTemp", "height", blockpid.Block.Height, "err", err.Error()) chainlog.Error("WriteBlockToDbTemp", "height", blockpid.Block.Height, "err", err.Error())
reply.IsOk = false reply.IsOk = false
......
...@@ -64,6 +64,17 @@ func (chain *BlockChain) Rollback() { ...@@ -64,6 +64,17 @@ func (chain *BlockChain) Rollback() {
} }
// 删除storedb中的状态高度 // 删除storedb中的状态高度
chain.sendDelStore(blockdetail.Block.StateHash, blockdetail.Block.Height) chain.sendDelStore(blockdetail.Block.StateHash, blockdetail.Block.Height)
// 删除之后,本地保存临时区块
if chain.cfg.RollbackSave {
lastHeightSave := false
if i == startHeight {
lastHeightSave = true
}
err = chain.WriteBlockToDbTemp(blockdetail.Block, lastHeightSave)
if err != nil {
panic(fmt.Sprintln("rollback WriteBlockToDbTemp fail", "height", blockdetail.Block.Height, "error ", err))
}
}
chainlog.Info("chain rollback ", "height: ", i, "blockheight", blockdetail.Block.Height, "hash", common.ToHex(blockdetail.Block.Hash()), "state hash", common.ToHex(blockdetail.Block.StateHash)) chainlog.Info("chain rollback ", "height: ", i, "blockheight", blockdetail.Block.Height, "hash", common.ToHex(blockdetail.Block.Hash()), "state hash", common.ToHex(blockdetail.Block.StateHash))
} }
} }
......
...@@ -8,6 +8,8 @@ import ( ...@@ -8,6 +8,8 @@ import (
"testing" "testing"
"time" "time"
"fmt"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
"github.com/33cn/chain33/util" "github.com/33cn/chain33/util"
"github.com/33cn/chain33/util/testnode" "github.com/33cn/chain33/util/testnode"
...@@ -23,42 +25,15 @@ func TestRollbackblock(t *testing.T) { ...@@ -23,42 +25,15 @@ func TestRollbackblock(t *testing.T) {
cfg, sub := testnode.GetDefaultConfig() cfg, sub := testnode.GetDefaultConfig()
cfg.BlockChain.RollbackBlock = 0 cfg.BlockChain.RollbackBlock = 0
mock33 := testnode.NewWithConfig(cfg, sub, nil) mock33 := testnode.NewWithConfig(cfg, sub, nil)
//发送交易
chain := mock33.GetBlockChain() chain := mock33.GetBlockChain()
chain.Rollbackblock() chain.Rollbackblock()
db := chain.GetDB() db := chain.GetDB()
kvs := getAllKeys(db) kvs := getAllKeys(db)
assert.Equal(t, len(kvs), 22) assert.Equal(t, len(kvs), 22)
defer mock33.Close() defer mock33.Close()
txs := util.GenCoinsTxs(mock33.GetGenesisKey(), 10)
for i := 0; i < len(txs); i++ { //发送交易
reply, err := mock33.GetAPI().SendTx(txs[i]) testMockSendTx(t, mock33)
assert.Nil(t, err)
assert.Equal(t, reply.IsOk, true)
}
mock33.WaitHeight(1)
txs = util.GenCoinsTxs(mock33.GetGenesisKey(), 10)
for i := 0; i < len(txs); i++ {
reply, err := mock33.GetAPI().SendTx(txs[i])
assert.Nil(t, err)
assert.Equal(t, reply.IsOk, true)
}
mock33.WaitHeight(2)
txs = util.GenNoneTxs(mock33.GetGenesisKey(), 1)
for i := 0; i < len(txs); i++ {
reply, err := mock33.GetAPI().SendTx(txs[i])
assert.Nil(t, err)
assert.Equal(t, reply.IsOk, true)
}
mock33.WaitHeight(3)
txs = util.GenNoneTxs(mock33.GetGenesisKey(), 2)
for i := 0; i < len(txs); i++ {
reply, err := mock33.GetAPI().SendTx(txs[i])
assert.Nil(t, err)
assert.Equal(t, reply.IsOk, true)
}
mock33.WaitHeight(4)
time.Sleep(time.Second)
chain.Rollbackblock() chain.Rollbackblock()
} }
...@@ -104,44 +79,50 @@ func TestRollback(t *testing.T) { ...@@ -104,44 +79,50 @@ func TestRollback(t *testing.T) {
cfg, sub := testnode.GetDefaultConfig() cfg, sub := testnode.GetDefaultConfig()
cfg.BlockChain.RollbackBlock = 2 cfg.BlockChain.RollbackBlock = 2
mock33 := testnode.NewWithConfig(cfg, sub, nil) mock33 := testnode.NewWithConfig(cfg, sub, nil)
chain := mock33.GetBlockChain()
db := chain.GetDB()
kvs := getAllKeys(db)
assert.Equal(t, len(kvs), 22)
defer mock33.Close()
//发送交易 //发送交易
testMockSendTx(t, mock33)
chain.Rollback()
require.Equal(t, int64(2), chain.GetBlockHeight())
}
func TestRollbackSave(t *testing.T) {
cfg, sub := testnode.GetDefaultConfig()
cfg.BlockChain.RollbackBlock = 2
cfg.BlockChain.RollbackSave = true
mock33 := testnode.NewWithConfig(cfg, sub, nil)
chain := mock33.GetBlockChain() chain := mock33.GetBlockChain()
db := chain.GetDB() db := chain.GetDB()
kvs := getAllKeys(db) kvs := getAllKeys(db)
assert.Equal(t, len(kvs), 22) assert.Equal(t, len(kvs), 22)
defer mock33.Close() defer mock33.Close()
txs := util.GenCoinsTxs(mock33.GetGenesisKey(), 10)
for i := 0; i < len(txs); i++ {
reply, err := mock33.GetAPI().SendTx(txs[i])
assert.Nil(t, err)
assert.Equal(t, reply.IsOk, true)
}
mock33.WaitHeight(1)
txs = util.GenCoinsTxs(mock33.GetGenesisKey(), 10)
for i := 0; i < len(txs); i++ {
reply, err := mock33.GetAPI().SendTx(txs[i])
assert.Nil(t, err)
assert.Equal(t, reply.IsOk, true)
}
mock33.WaitHeight(2)
txs = util.GenNoneTxs(mock33.GetGenesisKey(), 1)
for i := 0; i < len(txs); i++ {
reply, err := mock33.GetAPI().SendTx(txs[i])
assert.Nil(t, err)
assert.Equal(t, reply.IsOk, true)
}
mock33.WaitHeight(3)
txs = util.GenNoneTxs(mock33.GetGenesisKey(), 2)
for i := 0; i < len(txs); i++ {
reply, err := mock33.GetAPI().SendTx(txs[i])
assert.Nil(t, err)
assert.Equal(t, reply.IsOk, true)
}
mock33.WaitHeight(4)
time.Sleep(time.Second)
//发送交易
testMockSendTx(t, mock33)
height := chain.GetBlockHeight()
chain.Rollback() chain.Rollback()
// check
require.Equal(t, int64(2), chain.GetBlockHeight()) require.Equal(t, int64(2), chain.GetBlockHeight())
for i := height; i > 2; i-- {
key := []byte(fmt.Sprintf("TB:%012d", i))
_, err := chain.GetDB().Get(key)
assert.NoError(t, err)
}
value, err := chain.GetDB().Get([]byte("LTB:"))
assert.NoError(t, err)
assert.NotNil(t, value)
h := &types.Int64{}
err = types.Decode(value, h)
assert.NoError(t, err)
assert.Equal(t, height, h.Data)
} }
func TestRollbackPara(t *testing.T) { func TestRollbackPara(t *testing.T) {
...@@ -149,9 +130,17 @@ func TestRollbackPara(t *testing.T) { ...@@ -149,9 +130,17 @@ func TestRollbackPara(t *testing.T) {
cfg.BlockChain.RollbackBlock = 2 cfg.BlockChain.RollbackBlock = 2
cfg.BlockChain.IsParaChain = true cfg.BlockChain.IsParaChain = true
mock33 := testnode.NewWithConfig(cfg, sub, nil) mock33 := testnode.NewWithConfig(cfg, sub, nil)
//发送交易
chain := mock33.GetBlockChain() chain := mock33.GetBlockChain()
defer mock33.Close() defer mock33.Close()
//发送交易
testMockSendTx(t, mock33)
chain.Rollback()
require.Equal(t, int64(2), chain.GetBlockHeight())
}
func testMockSendTx(t *testing.T, mock33 *testnode.Chain33Mock) {
txs := util.GenCoinsTxs(mock33.GetGenesisKey(), 10) txs := util.GenCoinsTxs(mock33.GetGenesisKey(), 10)
for i := 0; i < len(txs); i++ { for i := 0; i < len(txs); i++ {
reply, err := mock33.GetAPI().SendTx(txs[i]) reply, err := mock33.GetAPI().SendTx(txs[i])
...@@ -181,7 +170,4 @@ func TestRollbackPara(t *testing.T) { ...@@ -181,7 +170,4 @@ func TestRollbackPara(t *testing.T) {
} }
mock33.WaitHeight(4) mock33.WaitHeight(4)
time.Sleep(time.Second) time.Sleep(time.Second)
chain.Rollback()
require.Equal(t, int64(2), chain.GetBlockHeight())
} }
...@@ -196,7 +196,59 @@ func (c *channelClient) CreateRawTxGroup(param *types.CreateTransactionGroup) ([ ...@@ -196,7 +196,59 @@ func (c *channelClient) CreateRawTxGroup(param *types.CreateTransactionGroup) ([
return txHex, nil return txHex, nil
} }
// CreateNoBalanceTxs create the multiple transaction with no balance
// 实际使用的时候要注意,一般情况下,不要传递 private key 到服务器端,除非是本地localhost 的服务。
func (c *channelClient) CreateNoBalanceTxs(in *types.NoBalanceTxs) (*types.Transaction, error) {
txNone := &types.Transaction{Execer: []byte(types.ExecName(types.NoneX)), Payload: []byte("no-fee-transaction")}
txNone.To = address.ExecAddress(string(txNone.Execer))
txNone, err := types.FormatTx(types.ExecName(types.NoneX), txNone)
if err != nil {
return nil, err
}
transactions := []*types.Transaction{txNone}
for _, txhex := range in.TxHexs {
tx, err := decodeTx(txhex)
if err != nil {
return nil, err
}
transactions = append(transactions, tx)
}
feeRate := types.GInt("MinFee")
//get proper fee rate
proper, err := c.GetProperFee(nil)
if err != nil {
log.Error("CreateNoBalance", "GetProperFeeErr", err)
return nil, err
}
if proper.GetProperFee() > feeRate {
feeRate = proper.ProperFee
}
group, err := types.CreateTxGroup(transactions, feeRate)
if err != nil {
return nil, err
}
err = group.Check(0, types.GInt("MinFee"), types.GInt("MaxFee"))
if err != nil {
return nil, err
}
newtx := group.Tx()
//如果可能要做签名
if in.PayAddr != "" || in.Privkey != "" {
rawTx := hex.EncodeToString(types.Encode(newtx))
req := &types.ReqSignRawTx{Addr: in.PayAddr, Privkey: in.Privkey, Expire: in.Expire, TxHex: rawTx, Index: 1}
signedTx, err := c.SignRawTx(req)
if err != nil {
return nil, err
}
return decodeTx(signedTx.TxHex)
}
return newtx, nil
}
// CreateNoBalanceTransaction create the transaction with no balance // CreateNoBalanceTransaction create the transaction with no balance
// 实际使用的时候要注意,一般情况下,不要传递 private key 到服务器端,除非是本地localhost 的服务。
func (c *channelClient) CreateNoBalanceTransaction(in *types.NoBalanceTx) (*types.Transaction, error) { func (c *channelClient) CreateNoBalanceTransaction(in *types.NoBalanceTx) (*types.Transaction, error) {
txNone := &types.Transaction{Execer: []byte(types.ExecName(types.NoneX)), Payload: []byte("no-fee-transaction")} txNone := &types.Transaction{Execer: []byte(types.ExecName(types.NoneX)), Payload: []byte("no-fee-transaction")}
txNone.To = address.ExecAddress(string(txNone.Execer)) txNone.To = address.ExecAddress(string(txNone.Execer))
......
...@@ -19,6 +19,16 @@ func (g *Grpc) SendTransaction(ctx context.Context, in *pb.Transaction) (*pb.Rep ...@@ -19,6 +19,16 @@ func (g *Grpc) SendTransaction(ctx context.Context, in *pb.Transaction) (*pb.Rep
return g.cli.SendTx(in) return g.cli.SendTx(in)
} }
// CreateNoBalanceTxs create multiple transaction with no balance
func (g *Grpc) CreateNoBalanceTxs(ctx context.Context, in *pb.NoBalanceTxs) (*pb.ReplySignRawTx, error) {
reply, err := g.cli.CreateNoBalanceTxs(in)
if err != nil {
return nil, err
}
tx := pb.Encode(reply)
return &pb.ReplySignRawTx{TxHex: hex.EncodeToString(tx)}, nil
}
// CreateNoBalanceTransaction create transaction with no balance // CreateNoBalanceTransaction create transaction with no balance
func (g *Grpc) CreateNoBalanceTransaction(ctx context.Context, in *pb.NoBalanceTx) (*pb.ReplySignRawTx, error) { func (g *Grpc) CreateNoBalanceTransaction(ctx context.Context, in *pb.NoBalanceTx) (*pb.ReplySignRawTx, error) {
reply, err := g.cli.CreateNoBalanceTransaction(in) reply, err := g.cli.CreateNoBalanceTransaction(in)
......
...@@ -1077,6 +1077,11 @@ func TestGrpc_CreateNoBalanceTransaction(t *testing.T) { ...@@ -1077,6 +1077,11 @@ func TestGrpc_CreateNoBalanceTransaction(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
} }
func TestGrpc_CreateNoBalanceTxs(t *testing.T) {
_, err := g.CreateNoBalanceTxs(getOkCtx(), &pb.NoBalanceTxs{TxHexs: []string{"0a05746f6b656e12413804223d0a0443434e5910a09c011a0d74657374207472616e73666572222231333559774e715367694551787577586650626d526d48325935334564673864343820a08d0630969a9fe6c4b9c7ba5d3a2231333559774e715367694551787577586650626d526d483259353345646738643438", "0a05746f6b656e12413804223d0a0443434e5910b0ea011a0d74657374207472616e73666572222231333559774e715367694551787577586650626d526d48325935334564673864343820a08d0630bca0a2dbc0f182e06f3a2231333559774e715367694551787577586650626d526d483259353345646738643438"}})
assert.NoError(t, err)
}
func TestGrpc_CreateRawTransaction(t *testing.T) { func TestGrpc_CreateRawTransaction(t *testing.T) {
_, err := g.CreateRawTransaction(getOkCtx(), &pb.CreateTx{}) _, err := g.CreateRawTransaction(getOkCtx(), &pb.CreateTx{})
assert.NoError(t, err) assert.NoError(t, err)
......
...@@ -73,6 +73,17 @@ func (c *Chain33) CreateRawTxGroup(in *types.CreateTransactionGroup, result *int ...@@ -73,6 +73,17 @@ func (c *Chain33) CreateRawTxGroup(in *types.CreateTransactionGroup, result *int
return nil return nil
} }
// CreateNoBlanaceTxs create multiple transaction with no balance
func (c *Chain33) CreateNoBlanaceTxs(in *types.NoBalanceTxs, result *string) error {
tx, err := c.cli.CreateNoBalanceTxs(in)
if err != nil {
return err
}
grouptx := hex.EncodeToString(types.Encode(tx))
*result = grouptx
return nil
}
// CreateNoBalanceTransaction create transaction with no balance // CreateNoBalanceTransaction create transaction with no balance
func (c *Chain33) CreateNoBalanceTransaction(in *types.NoBalanceTx, result *string) error { func (c *Chain33) CreateNoBalanceTransaction(in *types.NoBalanceTx, result *string) error {
tx, err := c.cli.CreateNoBalanceTransaction(in) tx, err := c.cli.CreateNoBalanceTransaction(in)
......
...@@ -1307,6 +1307,15 @@ func TestChain33_CreateNoBalanceTransaction(t *testing.T) { ...@@ -1307,6 +1307,15 @@ func TestChain33_CreateNoBalanceTransaction(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
} }
func TestChain33_CreateNoBalanceTxs(t *testing.T) {
api := new(mocks.QueueProtocolAPI)
chain33 := newTestChain33(api)
api.On("GetProperFee", mock.Anything).Return(&types.ReplyProperFee{ProperFee: 1000000}, nil)
var result string
err := chain33.CreateNoBlanaceTxs(&types.NoBalanceTxs{TxHexs: []string{"0a05746f6b656e12413804223d0a0443434e5910a09c011a0d74657374207472616e73666572222231333559774e715367694551787577586650626d526d48325935334564673864343820a08d0630969a9fe6c4b9c7ba5d3a2231333559774e715367694551787577586650626d526d483259353345646738643438", "0a05746f6b656e12413804223d0a0443434e5910b0ea011a0d74657374207472616e73666572222231333559774e715367694551787577586650626d526d48325935334564673864343820a08d0630bca0a2dbc0f182e06f3a2231333559774e715367694551787577586650626d526d483259353345646738643438"}}, &result)
assert.NoError(t, err)
}
func TestChain33_ExecWallet(t *testing.T) { func TestChain33_ExecWallet(t *testing.T) {
api := new(mocks.QueueProtocolAPI) api := new(mocks.QueueProtocolAPI)
client := newTestChain33(api) client := newTestChain33(api)
......
...@@ -146,6 +146,8 @@ type BlockChain struct { ...@@ -146,6 +146,8 @@ type BlockChain struct {
EnableReExecLocal bool `protobuf:"varint,14,opt,name=enableReExecLocal" json:"enableReExecLocal,omitempty"` EnableReExecLocal bool `protobuf:"varint,14,opt,name=enableReExecLocal" json:"enableReExecLocal,omitempty"`
// 区块回退 // 区块回退
RollbackBlock int64 `protobuf:"varint,15,opt,name=rollbackBlock" json:"rollbackBlock,omitempty"` RollbackBlock int64 `protobuf:"varint,15,opt,name=rollbackBlock" json:"rollbackBlock,omitempty"`
// 回退是否保存区块
RollbackSave bool `protobuf:"varint,16,opt,name=rollbackSave" json:"rollbackSave,omitempty"`
} }
// P2P 配置 // P2P 配置
......
...@@ -72,6 +72,36 @@ func (_m *Chain33Client) CreateNoBalanceTransaction(ctx context.Context, in *typ ...@@ -72,6 +72,36 @@ func (_m *Chain33Client) CreateNoBalanceTransaction(ctx context.Context, in *typ
return r0, r1 return r0, r1
} }
// CreateNoBalanceTxs provides a mock function with given fields: ctx, in, opts
func (_m *Chain33Client) CreateNoBalanceTxs(ctx context.Context, in *types.NoBalanceTxs, opts ...grpc.CallOption) (*types.ReplySignRawTx, error) {
_va := make([]interface{}, len(opts))
for _i := range opts {
_va[_i] = opts[_i]
}
var _ca []interface{}
_ca = append(_ca, ctx, in)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
var r0 *types.ReplySignRawTx
if rf, ok := ret.Get(0).(func(context.Context, *types.NoBalanceTxs, ...grpc.CallOption) *types.ReplySignRawTx); ok {
r0 = rf(ctx, in, opts...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ReplySignRawTx)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *types.NoBalanceTxs, ...grpc.CallOption) error); ok {
r1 = rf(ctx, in, opts...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// CreateRawTransaction provides a mock function with given fields: ctx, in, opts // CreateRawTransaction provides a mock function with given fields: ctx, in, opts
func (_m *Chain33Client) CreateRawTransaction(ctx context.Context, in *types.CreateTx, opts ...grpc.CallOption) (*types.UnsignTx, error) { func (_m *Chain33Client) CreateRawTransaction(ctx context.Context, in *types.CreateTx, opts ...grpc.CallOption) (*types.UnsignTx, error) {
_va := make([]interface{}, len(opts)) _va := make([]interface{}, len(opts))
......
...@@ -147,6 +147,9 @@ service chain33 { ...@@ -147,6 +147,9 @@ service chain33 {
// 获取是否达到fork高度 // 获取是否达到fork高度
rpc GetFork(ReqKey) returns (Int64) {} rpc GetFork(ReqKey) returns (Int64) {}
rpc CreateNoBalanceTxs(NoBalanceTxs) returns (ReplySignRawTx) {}
//通过seq以及title获取对应平行连的交易 //通过seq以及title获取对应平行连的交易
rpc GetParaTxByTitle(ReqParaTxByTitle) returns (ParaTxDetails) {} rpc GetParaTxByTitle(ReqParaTxByTitle) returns (ParaTxDetails) {}
} }
...@@ -69,6 +69,14 @@ message UnsignTx { ...@@ -69,6 +69,14 @@ message UnsignTx {
bytes data = 1; bytes data = 1;
} }
// 支持构造多笔nobalance的交易 payAddr 可以支持 1. 地址 2. 私钥
message NoBalanceTxs {
repeated string txHexs = 1;
string payAddr = 2;
string privkey = 3;
string expire = 4;
}
// payAddr 可以支持 1. 地址 2. 私钥 // payAddr 可以支持 1. 地址 2. 私钥
message NoBalanceTx { message NoBalanceTx {
string txHex = 1; string txHex = 1;
......
...@@ -51,6 +51,7 @@ var ( ...@@ -51,6 +51,7 @@ var (
fixtime = flag.Bool("fixtime", false, "fix time") fixtime = flag.Bool("fixtime", false, "fix time")
waitPid = flag.Bool("waitpid", false, "p2p stuck until seed save info wallet & wallet unlock") waitPid = flag.Bool("waitpid", false, "p2p stuck until seed save info wallet & wallet unlock")
rollback = flag.Int64("rollback", 0, "rollback block") rollback = flag.Int64("rollback", 0, "rollback block")
save = flag.Bool("save", false, "rollback save temporary block")
) )
//RunChain33 : run Chain33 //RunChain33 : run Chain33
...@@ -155,6 +156,7 @@ func RunChain33(name string) { ...@@ -155,6 +156,7 @@ func RunChain33(name string) {
log.Info("loading blockchain module") log.Info("loading blockchain module")
cfg.BlockChain.RollbackBlock = *rollback cfg.BlockChain.RollbackBlock = *rollback
cfg.BlockChain.RollbackSave = *save
chain := blockchain.New(cfg.BlockChain) chain := blockchain.New(cfg.BlockChain)
chain.SetQueueClient(q.Client()) chain.SetQueueClient(q.Client())
......
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