Commit 47bbff03 authored by 陈德海's avatar 陈德海

merge mempool trade

parents 053827a8 5e735848
...@@ -62,7 +62,7 @@ grpcFuncWhitelist=["*"] ...@@ -62,7 +62,7 @@ grpcFuncWhitelist=["*"]
[mempool] [mempool]
name="trade" name="timeline"
poolCacheSize=10240 poolCacheSize=10240
minTxFee=100000 minTxFee=100000
maxTxNumPerAccount=10000 maxTxNumPerAccount=10000
...@@ -77,8 +77,8 @@ poolCacheSize=10240 ...@@ -77,8 +77,8 @@ poolCacheSize=10240
minTxFee=100000 minTxFee=100000
maxTxNumPerAccount=10000 maxTxNumPerAccount=10000
timeParam=1 #时间占价格比例 timeParam=1 #时间占价格比例
priceConstant=1 #一个合适的常量 priceConstant=1544 #手续费相对于时间的一个合适的常量,取当前unxi时间戳前四位数,排序时手续费高1e-5~=快1s
pricePower=0 #手续费占常量比例 pricePower=1 #常量比例
[consensus] [consensus]
name="ticket" name="ticket"
......
...@@ -48,7 +48,7 @@ type suiteParaCommitMsg struct { ...@@ -48,7 +48,7 @@ type suiteParaCommitMsg struct {
block *blockchain.BlockChain block *blockchain.BlockChain
exec *executor.Executor exec *executor.Executor
store queue.Module store queue.Module
mem *mempool.Mempool mem queue.Module
network *p2p.P2p network *p2p.P2p
} }
...@@ -84,17 +84,15 @@ func (s *suiteParaCommitMsg) initEnv(cfg *types.Config, sub *types.ConfigSubModu ...@@ -84,17 +84,15 @@ func (s *suiteParaCommitMsg) initEnv(cfg *types.Config, sub *types.ConfigSubModu
s.para.grpcClient = s.grpcCli s.para.grpcClient = s.grpcCli
s.para.SetQueueClient(q.Client()) s.para.SetQueueClient(q.Client())
s.mem = mempool.New(cfg.MemPool) s.mem = mempool.New(cfg.Mempool, nil)
s.mem.SetQueueClient(q.Client()) s.mem.SetQueueClient(q.Client())
s.mem.SetSync(true) s.mem.Wait()
s.mem.WaitPollLastHeader()
s.network = p2p.New(cfg.P2P) s.network = p2p.New(cfg.P2P)
s.network.SetQueueClient(q.Client()) s.network.SetQueueClient(q.Client())
s.para.wg.Add(1) s.para.wg.Add(1)
go walletProcess(q, s.para) go walletProcess(q, s.para)
} }
func walletProcess(q queue.Queue, para *client) { func walletProcess(q queue.Queue, para *client) {
......
...@@ -51,6 +51,7 @@ verMix=118 ...@@ -51,6 +51,7 @@ verMix=118
verMax=119 verMax=119
[mempool] [mempool]
name="timeline"
poolCacheSize=10240 poolCacheSize=10240
minTxFee=100000 minTxFee=100000
......
...@@ -62,14 +62,14 @@ func TestPbft(t *testing.T) { ...@@ -62,14 +62,14 @@ func TestPbft(t *testing.T) {
clearTestData() clearTestData()
} }
func initEnvPbft() (queue.Queue, *blockchain.BlockChain, *p2p.P2p, queue.Module, *mempool.Mempool, queue.Module, queue.Module, queue.Module) { func initEnvPbft() (queue.Queue, *blockchain.BlockChain, *p2p.P2p, queue.Module, queue.Module, *executor.Executor, queue.Module, queue.Module) {
var q = queue.New("channel") var q = queue.New("channel")
flag.Parse() flag.Parse()
cfg, sub := types.InitCfg("chain33.test.toml") cfg, sub := types.InitCfg("chain33.test.toml")
types.Init(cfg.Title, cfg) types.Init(cfg.Title, cfg)
chain := blockchain.New(cfg.BlockChain) chain := blockchain.New(cfg.BlockChain)
chain.SetQueueClient(q.Client()) chain.SetQueueClient(q.Client())
mem := mempool.New(cfg.MemPool) mem := mempool.New(cfg.Mempool, nil)
mem.SetQueueClient(q.Client()) mem.SetQueueClient(q.Client())
exec := executor.New(cfg.Exec, sub.Exec) exec := executor.New(cfg.Exec, sub.Exec)
exec.SetQueueClient(q.Client()) exec.SetQueueClient(q.Client())
......
...@@ -59,6 +59,7 @@ jrpcFuncWhitelist=["*"] ...@@ -59,6 +59,7 @@ jrpcFuncWhitelist=["*"]
grpcFuncWhitelist=["*"] grpcFuncWhitelist=["*"]
[mempool] [mempool]
name="timeline"
poolCacheSize=10240 poolCacheSize=10240
minTxFee=100000 minTxFee=100000
......
...@@ -63,7 +63,7 @@ func RaftPerf() { ...@@ -63,7 +63,7 @@ func RaftPerf() {
sendReplyList(q) sendReplyList(q)
} }
func initEnvRaft() (queue.Queue, *blockchain.BlockChain, queue.Module, *mempool.Mempool, queue.Module, queue.Module, queue.Module) { func initEnvRaft() (queue.Queue, *blockchain.BlockChain, queue.Module, queue.Module, *executor.Executor, queue.Module, queue.Module) {
var q = queue.New("channel") var q = queue.New("channel")
flag.Parse() flag.Parse()
cfg, sub := types.InitCfg("chain33.test.toml") cfg, sub := types.InitCfg("chain33.test.toml")
...@@ -80,7 +80,7 @@ func initEnvRaft() (queue.Queue, *blockchain.BlockChain, queue.Module, *mempool. ...@@ -80,7 +80,7 @@ func initEnvRaft() (queue.Queue, *blockchain.BlockChain, queue.Module, *mempool.
cs := NewRaftCluster(cfg.Consensus, sub.Consensus["raft"]) cs := NewRaftCluster(cfg.Consensus, sub.Consensus["raft"])
cs.SetQueueClient(q.Client()) cs.SetQueueClient(q.Client())
mem := mempool.New(cfg.MemPool) mem := mempool.New(cfg.Mempool, nil)
mem.SetQueueClient(q.Client()) mem.SetQueueClient(q.Client())
network := p2p.New(cfg.P2P) network := p2p.New(cfg.P2P)
......
...@@ -60,6 +60,7 @@ jrpcFuncWhitelist=["*"] ...@@ -60,6 +60,7 @@ jrpcFuncWhitelist=["*"]
grpcFuncWhitelist=["*"] grpcFuncWhitelist=["*"]
[mempool] [mempool]
name="timeline"
poolCacheSize=10240 poolCacheSize=10240
minTxFee=100000 minTxFee=100000
......
...@@ -76,7 +76,7 @@ func RaftPerf() { ...@@ -76,7 +76,7 @@ func RaftPerf() {
time.Sleep(10 * time.Second) time.Sleep(10 * time.Second)
} }
func initEnvTendermint() (queue.Queue, *blockchain.BlockChain, queue.Module, *mempool.Mempool, queue.Module, queue.Module, queue.Module) { func initEnvTendermint() (queue.Queue, *blockchain.BlockChain, queue.Module, queue.Module, *executor.Executor, queue.Module, queue.Module) {
var q = queue.New("channel") var q = queue.New("channel")
flag.Parse() flag.Parse()
cfg, sub := types.InitCfg("chain33.test.toml") cfg, sub := types.InitCfg("chain33.test.toml")
...@@ -93,7 +93,7 @@ func initEnvTendermint() (queue.Queue, *blockchain.BlockChain, queue.Module, *me ...@@ -93,7 +93,7 @@ func initEnvTendermint() (queue.Queue, *blockchain.BlockChain, queue.Module, *me
cs := New(cfg.Consensus, sub.Consensus["tendermint"]) cs := New(cfg.Consensus, sub.Consensus["tendermint"])
cs.SetQueueClient(q.Client()) cs.SetQueueClient(q.Client())
mem := mempool.New(cfg.MemPool) mem := mempool.New(cfg.Mempool, nil)
mem.SetQueueClient(q.Client()) mem.SetQueueClient(q.Client())
network := p2p.New(cfg.P2P) network := p2p.New(cfg.P2P)
......
...@@ -60,6 +60,7 @@ jrpcFuncWhitelist=["*"] ...@@ -60,6 +60,7 @@ jrpcFuncWhitelist=["*"]
grpcFuncWhitelist=["*"] grpcFuncWhitelist=["*"]
[mempool] [mempool]
name="timeline"
poolCacheSize=10240 poolCacheSize=10240
minTxFee=100000 minTxFee=100000
maxTxNumPerAccount=10000 maxTxNumPerAccount=10000
......
...@@ -201,6 +201,11 @@ func (client *Client) setTicket(tlist *ty.ReplyTicketList, privmap map[string]cr ...@@ -201,6 +201,11 @@ func (client *Client) setTicket(tlist *ty.ReplyTicketList, privmap map[string]cr
client.ticketmu.Lock() client.ticketmu.Lock()
defer client.ticketmu.Unlock() defer client.ticketmu.Unlock()
client.ticketsMap = make(map[string]*ty.Ticket) client.ticketsMap = make(map[string]*ty.Ticket)
if tlist == nil || privmap == nil {
client.ticketsMap = nil
client.privmap = nil
return
}
for _, ticket := range tlist.Tickets { for _, ticket := range tlist.Tickets {
client.ticketsMap[ticket.GetTicketId()] = ticket client.ticketsMap[ticket.GetTicketId()] = ticket
} }
......
...@@ -104,11 +104,29 @@ func TestTicketMap(t *testing.T) { ...@@ -104,11 +104,29 @@ func TestTicketMap(t *testing.T) {
{TicketId: "3333"}, {TicketId: "3333"},
{TicketId: "4444"}, {TicketId: "4444"},
} }
privmap := make(map[string]crypto.PrivKey)
//通过privkey生成一个pubkey然后换算成对应的addr
cr, _ := crypto.New("secp256k1")
priv, _ := cr.PrivKeyFromBytes([]byte("2116459C0EC8ED01AA0EEAE35CAC5C96F94473F7816F114873291217303F6989"))
privmap["1111"] = priv
privmap["2222"] = priv
privmap["3333"] = priv
privmap["4444"] = priv
assert.Equal(t, c.getTicketCount(), int64(0)) assert.Equal(t, c.getTicketCount(), int64(0))
c.setTicket(ticketList, nil) c.setTicket(ticketList, privmap)
assert.Equal(t, c.getTicketCount(), int64(4)) assert.Equal(t, c.getTicketCount(), int64(4))
c.delTicket("3333") c.delTicket("3333")
assert.Equal(t, c.getTicketCount(), int64(3)) assert.Equal(t, c.getTicketCount(), int64(3))
c.setTicket(ticketList, nil)
assert.Equal(t, c.getTicketCount(), int64(0))
c.setTicket(nil, privmap)
assert.Equal(t, c.getTicketCount(), int64(0))
c.setTicket(nil, nil)
assert.Equal(t, c.getTicketCount(), int64(0))
} }
func TestProcEvent(t *testing.T) { func TestProcEvent(t *testing.T) {
......
...@@ -62,6 +62,7 @@ grpcFuncWhitelist=["*"] ...@@ -62,6 +62,7 @@ grpcFuncWhitelist=["*"]
mainnetJrpcAddr= "http://localhost:8801" mainnetJrpcAddr= "http://localhost:8801"
[mempool] [mempool]
name="timeline"
poolCacheSize=10240 poolCacheSize=10240
minTxFee=100000 minTxFee=100000
maxTxNumPerAccount=10000 maxTxNumPerAccount=10000
......
...@@ -63,6 +63,7 @@ grpcFuncWhitelist=["*"] ...@@ -63,6 +63,7 @@ grpcFuncWhitelist=["*"]
mainnetJrpcAddr= "http://localhost:8801" mainnetJrpcAddr= "http://localhost:8801"
[mempool] [mempool]
name="timeline"
poolCacheSize=10240 poolCacheSize=10240
minTxFee=100000 minTxFee=100000
maxTxNumPerAccount=10000 maxTxNumPerAccount=10000
......
...@@ -100,9 +100,8 @@ func (mock *testDataMock) initMember() { ...@@ -100,9 +100,8 @@ func (mock *testDataMock) initMember() {
if mock.mockMempool { if mock.mockMempool {
mock.mockMempoolProc(q) mock.mockMempoolProc(q)
} else { } else {
mempool := mempool.New(cfg.MemPool) mempool := mempool.New(cfg.Mempool, nil)
mempool.SetQueueClient(q.Client()) mempool.SetQueueClient(q.Client())
mempool.SetMinFee(1e5)
mock.modules = append(mock.modules, mempool) mock.modules = append(mock.modules, mempool)
} }
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
package executor package executor
import ( import (
"errors"
"fmt"
"strconv" "strconv"
"github.com/33cn/chain33/account" "github.com/33cn/chain33/account"
...@@ -412,10 +414,34 @@ func (action *tradeAction) tradeRevokeSell(revoke *pty.TradeForRevokeSell) (*typ ...@@ -412,10 +414,34 @@ func (action *tradeAction) tradeRevokeSell(revoke *pty.TradeForRevokeSell) (*typ
return &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}, nil return &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}, nil
} }
//不同合约之间查询的需求后面要考虑,现在先重复处理一下,原则上不能直接引用其他合约的代码
//后面可能会有一套查询规则 和 写规则, 合约对其他合约只读
func calcTokenKey(token string) (key []byte) {
tokenCreated := "mavl-token-"
return []byte(fmt.Sprintf(tokenCreated+"%s", token))
}
func checkTokenExist(token string, db dbm.KV) bool {
_, err := db.Get(calcTokenKey(token))
return err == nil
}
func (action *tradeAction) tradeBuyLimit(buy *pty.TradeForBuyLimit) (*types.Receipt, error) { func (action *tradeAction) tradeBuyLimit(buy *pty.TradeForBuyLimit) (*types.Receipt, error) {
// ErrTokenNotExist error token symbol not exist
errTokenNotExist := errors.New("ErrTokenSymbolNotExist")
if buy.TotalBoardlot < 0 || buy.PricePerBoardlot < 0 || buy.MinBoardlot < 0 || buy.AmountPerBoardlot < 0 { if buy.TotalBoardlot < 0 || buy.PricePerBoardlot < 0 || buy.MinBoardlot < 0 || buy.AmountPerBoardlot < 0 {
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
// 这个检查会比较鸡肋, 按目前的想法的能支持更多的资产, 各种资产检查不一样
// 可以先让订单成功, 如果不合适, 自己撤单也行
// 或后续跨合约注册一个检测的函数
if buy.AssetExec == "" || buy.AssetExec == defaultAssetExec {
// check token exist
if !checkTokenExist(buy.TokenSymbol, action.db) {
return nil, errTokenNotExist
}
}
if !checkAsset(action.height, buy.AssetExec, buy.TokenSymbol) { if !checkAsset(action.height, buy.AssetExec, buy.TokenSymbol) {
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
......
...@@ -24,7 +24,4 @@ var ( ...@@ -24,7 +24,4 @@ var (
// TODO // TODO
func init() { func init() {
processNum = runtime.NumCPU() processNum = runtime.NumCPU()
//if processNum >= 2 {
//processNum -= 1
//}
} }
...@@ -943,7 +943,7 @@ func (bs *BlockStore) saveBlockSequence(storeBatch dbm.Batch, hash []byte, heigh ...@@ -943,7 +943,7 @@ func (bs *BlockStore) saveBlockSequence(storeBatch dbm.Batch, hash []byte, heigh
storeBatch.Set(calcSequenceToHashKey(newSequence), BlockSequenceByte) storeBatch.Set(calcSequenceToHashKey(newSequence), BlockSequenceByte)
//parachain hash->seq 只记录add block时的hash和seq对应关系 //parachain hash->seq 只记录add block时的hash和seq对应关系
if Type == AddBlock && isParaChain { if Type == AddBlock {
Sequencebytes := types.Encode(&types.Int64{Data: newSequence}) Sequencebytes := types.Encode(&types.Int64{Data: newSequence})
storeBatch.Set(calcHashToSequenceKey(hash), Sequencebytes) storeBatch.Set(calcHashToSequenceKey(hash), Sequencebytes)
} }
...@@ -991,7 +991,7 @@ func (bs *BlockStore) GetSequenceByHash(hash []byte) (int64, error) { ...@@ -991,7 +991,7 @@ func (bs *BlockStore) GetSequenceByHash(hash []byte) (int64, error) {
if err != dbm.ErrNotFoundInDb { if err != dbm.ErrNotFoundInDb {
storeLog.Error("GetSequenceByHash", "error", err) storeLog.Error("GetSequenceByHash", "error", err)
} }
return -1, types.ErrHeightNotExist return -1, types.ErrHashNotExist
} }
err = types.Decode(seqbytes, &seq) err = types.Decode(seqbytes, &seq)
......
...@@ -634,6 +634,7 @@ func testGetSeqByHash(t *testing.T, blockchain *blockchain.BlockChain) { ...@@ -634,6 +634,7 @@ func testGetSeqByHash(t *testing.T, blockchain *blockchain.BlockChain) {
reqBlock.IsDetail = true reqBlock.IsDetail = true
hashes := make([][]byte, 1) hashes := make([][]byte, 1)
Sequences, err := blockchain.GetBlockSequences(&reqBlock) Sequences, err := blockchain.GetBlockSequences(&reqBlock)
if err == nil && Sequences != nil { if err == nil && Sequences != nil {
for index, sequence := range Sequences.Items { for index, sequence := range Sequences.Items {
hashes[index] = sequence.Hash hashes[index] = sequence.Hash
...@@ -641,8 +642,8 @@ func testGetSeqByHash(t *testing.T, blockchain *blockchain.BlockChain) { ...@@ -641,8 +642,8 @@ func testGetSeqByHash(t *testing.T, blockchain *blockchain.BlockChain) {
} }
seq, _ := blockchain.ProcGetSeqByHash(hashes[0]) seq, _ := blockchain.ProcGetSeqByHash(hashes[0])
if seq != -1 { if seq == -1 {
t.Error("testGetSeqByHash only para chain GetSeqByHash ") t.Error(" GetSeqByHash err")
} }
chainlog.Info("testGetSeqByHash end --------------------") chainlog.Info("testGetSeqByHash end --------------------")
......
...@@ -455,11 +455,13 @@ func (chain *BlockChain) addParaChainBlockDetail(msg queue.Message) { ...@@ -455,11 +455,13 @@ func (chain *BlockChain) addParaChainBlockDetail(msg queue.Message) {
//parachian 通过blockhash获取对应的seq,只记录了addblock时的seq //parachian 通过blockhash获取对应的seq,只记录了addblock时的seq
func (chain *BlockChain) getSeqByHash(msg queue.Message) { func (chain *BlockChain) getSeqByHash(msg queue.Message) {
var sequence types.Int64
blockhash := (msg.Data).(*types.ReqHash) blockhash := (msg.Data).(*types.ReqHash)
sequence.Data, _ = chain.ProcGetSeqByHash(blockhash.Hash) seq, err := chain.ProcGetSeqByHash(blockhash.Hash)
msg.Reply(chain.client.NewMessage("rpc", types.EventGetSeqByHash, &sequence)) if err != nil {
chainlog.Error("getSeqByHash", "err", err.Error())
msg.Reply(chain.client.NewMessage("rpc", types.EventReply, err))
}
msg.Reply(chain.client.NewMessage("rpc", types.EventGetSeqByHash, &types.Int64{Data: seq}))
} }
//获取指定前缀key的数量 //获取指定前缀key的数量
......
...@@ -25,7 +25,7 @@ func TestReindex(t *testing.T) { ...@@ -25,7 +25,7 @@ func TestReindex(t *testing.T) {
chain := mock33.GetBlockChain() chain := mock33.GetBlockChain()
db := chain.GetDB() db := chain.GetDB()
kvs := getAllKeys(db) kvs := getAllKeys(db)
assert.Equal(t, len(kvs), 19) assert.Equal(t, len(kvs), 20)
defer mock33.Close() defer mock33.Close()
txs := util.GenCoinsTxs(mock33.GetGenesisKey(), 10) txs := util.GenCoinsTxs(mock33.GetGenesisKey(), 10)
for i := 0; i < len(txs); i++ { for i := 0; i < len(txs); i++ {
......
...@@ -8,7 +8,7 @@ set -o pipefail ...@@ -8,7 +8,7 @@ set -o pipefail
# os: ubuntu16.04 x64 # os: ubuntu16.04 x64
#chain33 dapp autotest root directory #chain33 dapp autotest root directory
declare -a Chain33AutoTestDirs=("system" "plugin" "vendor/github.com/33cn/chain33/system") declare -a Chain33AutoTestDirs=("system" "plugin" "vendor/github.com/33cn/chain33/system" "vendor/github.com/33cn/plugin/plugin")
#copy auto test to specific directory #copy auto test to specific directory
# check args # check args
......
...@@ -101,6 +101,9 @@ func (m *mockBlockChain) SetQueueClient(q queue.Queue) { ...@@ -101,6 +101,9 @@ func (m *mockBlockChain) SetQueueClient(q queue.Queue) {
} else { } else {
msg.ReplyErr("Do not support", types.ErrInvalidParam) msg.ReplyErr("Do not support", types.ErrInvalidParam)
} }
case types.EventGetSeqByHash:
msg.Reply(client.NewMessage(blockchainKey, types.EventReplyQuery, &types.Int64{Data: 1}))
case types.EventIsSync: case types.EventIsSync:
msg.Reply(client.NewMessage(blockchainKey, types.EventReplyIsSync, &types.IsCaughtUp{})) msg.Reply(client.NewMessage(blockchainKey, types.EventReplyIsSync, &types.IsCaughtUp{}))
case types.EventIsNtpClockSync: case types.EventIsNtpClockSync:
......
...@@ -499,6 +499,29 @@ func (_m *QueueProtocolAPI) GetSeqCallBackLastNum(param *types.ReqString) (*type ...@@ -499,6 +499,29 @@ func (_m *QueueProtocolAPI) GetSeqCallBackLastNum(param *types.ReqString) (*type
return r0, r1 return r0, r1
} }
// GetSequenceByHash provides a mock function with given fields: param
func (_m *QueueProtocolAPI) GetSequenceByHash(param *types.ReqHash) (*types.Int64, error) {
ret := _m.Called(param)
var r0 *types.Int64
if rf, ok := ret.Get(0).(func(*types.ReqHash) *types.Int64); ok {
r0 = rf(param)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.Int64)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(*types.ReqHash) error); ok {
r1 = rf(param)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetTransactionByAddr provides a mock function with given fields: param // GetTransactionByAddr provides a mock function with given fields: param
func (_m *QueueProtocolAPI) GetTransactionByAddr(param *types.ReqAddr) (*types.ReplyTxInfos, error) { func (_m *QueueProtocolAPI) GetTransactionByAddr(param *types.ReqAddr) (*types.ReplyTxInfos, error) {
ret := _m.Called(param) ret := _m.Called(param)
......
...@@ -898,6 +898,25 @@ func (q *QueueProtocol) GetLastBlockSequence() (*types.Int64, error) { ...@@ -898,6 +898,25 @@ func (q *QueueProtocol) GetLastBlockSequence() (*types.Int64, error) {
return nil, types.ErrTypeAsset return nil, types.ErrTypeAsset
} }
// GetSequenceByHash 通过hash获取对应的执行序列号
func (q *QueueProtocol) GetSequenceByHash(param *types.ReqHash) (*types.Int64, error) {
if param == nil {
err := types.ErrInvalidParam
log.Error("GetSequenceByHash", "Error", err)
return nil, err
}
msg, err := q.query(blockchainKey, types.EventGetSeqByHash, param)
if err != nil {
log.Error("GetSequenceByHash", "Error", err.Error())
return nil, err
}
if reply, ok := msg.GetData().(*types.Int64); ok {
return reply, nil
}
return nil, types.ErrTypeAsset
}
// WalletCreateTx create transaction // WalletCreateTx create transaction
func (q *QueueProtocol) WalletCreateTx(param *types.ReqCreateTransaction) (*types.Transaction, error) { func (q *QueueProtocol) WalletCreateTx(param *types.ReqCreateTransaction) (*types.Transaction, error) {
msg, err := q.query(walletKey, types.EventWalletCreateTx, param) msg, err := q.query(walletKey, types.EventWalletCreateTx, param)
......
...@@ -806,6 +806,7 @@ func TestGRPC(t *testing.T) { ...@@ -806,6 +806,7 @@ func TestGRPC(t *testing.T) {
testGetBlockOverviewGRPC(t, &grpcMock) testGetBlockOverviewGRPC(t, &grpcMock)
testGetAddrOverviewGRPC(t, &grpcMock) testGetAddrOverviewGRPC(t, &grpcMock)
testGetBlockHashGRPC(t, &grpcMock) testGetBlockHashGRPC(t, &grpcMock)
testGetSequenceByHashGRPC(t, &grpcMock)
testGenSeedGRPC(t, &grpcMock) testGenSeedGRPC(t, &grpcMock)
testGetSeedGRPC(t, &grpcMock) testGetSeedGRPC(t, &grpcMock)
testSaveSeedGRPC(t, &grpcMock) testSaveSeedGRPC(t, &grpcMock)
...@@ -1131,3 +1132,11 @@ func testSendTxGRPC(t *testing.T, rpc *mockGRPCSystem) { ...@@ -1131,3 +1132,11 @@ func testSendTxGRPC(t *testing.T, rpc *mockGRPCSystem) {
t.Error("Call SendTransaction Failed.", err) t.Error("Call SendTransaction Failed.", err)
} }
} }
func testGetSequenceByHashGRPC(t *testing.T, rpc *mockGRPCSystem) {
var res types.Int64
err := rpc.newRpcCtx("GetSequenceByHash", &types.ReqHash{}, &res)
if err != nil {
t.Error("Call GetSequenceByHash Failed.", err)
}
}
...@@ -111,6 +111,8 @@ type QueueProtocolAPI interface { ...@@ -111,6 +111,8 @@ type QueueProtocolAPI interface {
GetBlockSequences(param *types.ReqBlocks) (*types.BlockSequences, error) GetBlockSequences(param *types.ReqBlocks) (*types.BlockSequences, error)
//types.EventGetBlockByHashes: //types.EventGetBlockByHashes:
GetBlockByHashes(param *types.ReqHashes) (*types.BlockDetails, error) GetBlockByHashes(param *types.ReqHashes) (*types.BlockDetails, error)
//types.EventGetSequenceByHash:
GetSequenceByHash(param *types.ReqHash) (*types.Int64, error)
// --------------- blockchain interfaces end // --------------- blockchain interfaces end
......
...@@ -315,6 +315,12 @@ func (c *GrpcCtx) Run() (err error) { ...@@ -315,6 +315,12 @@ func (c *GrpcCtx) Run() (err error) {
*c.Res.(*types.NodeNetInfo) = *reply *c.Res.(*types.NodeNetInfo) = *reply
} }
errRet = err errRet = err
case "GetSequenceByHash":
reply, err := rpc.GetSequenceByHash(context.Background(), c.Params.(*types.ReqHash))
if err == nil {
*c.Res.(*types.Int64) = *reply
}
errRet = err
default: default:
errRet = errors.New(fmt.Sprintf("Unsupport method %v", c.Method)) errRet = errors.New(fmt.Sprintf("Unsupport method %v", c.Method))
} }
......
...@@ -18,13 +18,24 @@ import ( ...@@ -18,13 +18,24 @@ import (
var addrSeed = []byte("address seed bytes for public key") var addrSeed = []byte("address seed bytes for public key")
var addressCache *lru.Cache var addressCache *lru.Cache
var checkAddressCache *lru.Cache var checkAddressCache *lru.Cache
var multisignCache *lru.Cache
var multiCheckAddressCache *lru.Cache
var errVersion = errors.New("check version error")
//MaxExecNameLength 执行器名最大长度 //MaxExecNameLength 执行器名最大长度
const MaxExecNameLength = 100 const MaxExecNameLength = 100
//NormalVer 普通地址的版本号
const NormalVer byte = 0
//MultiSignVer 多重签名地址的版本号
const MultiSignVer byte = 5
func init() { func init() {
multisignCache, _ = lru.New(10240)
addressCache, _ = lru.New(10240) addressCache, _ = lru.New(10240)
checkAddressCache, _ = lru.New(10240) checkAddressCache, _ = lru.New(10240)
multiCheckAddressCache, _ = lru.New(10240)
} }
//ExecPubKey 计算公钥 //ExecPubKey 计算公钥
...@@ -44,12 +55,23 @@ func ExecAddress(name string) string { ...@@ -44,12 +55,23 @@ func ExecAddress(name string) string {
if value, ok := addressCache.Get(name); ok { if value, ok := addressCache.Get(name); ok {
return value.(string) return value.(string)
} }
addr := PubKeyToAddress(ExecPubkey(name)) addr := GetExecAddress(name)
addrstr := addr.String() addrstr := addr.String()
addressCache.Add(name, addrstr) addressCache.Add(name, addrstr)
return addrstr return addrstr
} }
//MultiSignAddress create a multi sign address
func MultiSignAddress(pubkey []byte) string {
if value, ok := multisignCache.Get(string(pubkey)); ok {
return value.(string)
}
addr := HashToAddress(MultiSignVer, pubkey)
addrstr := addr.String()
multisignCache.Add(string(pubkey), addrstr)
return addrstr
}
//ExecPubkey 计算公钥 //ExecPubkey 计算公钥
func ExecPubkey(name string) []byte { func ExecPubkey(name string) []byte {
if len(name) > MaxExecNameLength { if len(name) > MaxExecNameLength {
...@@ -64,35 +86,27 @@ func ExecPubkey(name string) []byte { ...@@ -64,35 +86,27 @@ func ExecPubkey(name string) []byte {
//GetExecAddress 获取地址 //GetExecAddress 获取地址
func GetExecAddress(name string) *Address { func GetExecAddress(name string) *Address {
if len(name) > MaxExecNameLength { hash := ExecPubkey(name)
panic("name too long")
}
var bname [200]byte
buf := append(bname[:0], addrSeed...)
buf = append(buf, []byte(name)...)
hash := common.Sha2Sum(buf)
addr := PubKeyToAddress(hash[:]) addr := PubKeyToAddress(hash[:])
return addr return addr
} }
//PubKeyToAddress 公钥转为地址 //PubKeyToAddress 公钥转为地址
func PubKeyToAddress(in []byte) *Address { func PubKeyToAddress(in []byte) *Address {
return HashToAddress(NormalVer, in)
}
//HashToAddress hash32 to address
func HashToAddress(version byte, in []byte) *Address {
a := new(Address) a := new(Address)
a.Pubkey = make([]byte, len(in)) a.Pubkey = make([]byte, len(in))
copy(a.Pubkey[:], in[:]) copy(a.Pubkey[:], in[:])
a.Version = 0 a.Version = version
a.Hash160 = common.Rimp160AfterSha256(in) a.Hash160 = common.Rimp160AfterSha256(in)
return a return a
} }
//CheckAddress 检查地址 func checkAddress(ver byte, addr string) (e error) {
func CheckAddress(addr string) (e error) {
if value, ok := checkAddressCache.Get(addr); ok {
if value == nil {
return nil
}
return value.(error)
}
dec := base58.Decode(addr) dec := base58.Decode(addr)
if dec == nil { if dec == nil {
e = errors.New("Cannot decode b58 string '" + addr + "'") e = errors.New("Cannot decode b58 string '" + addr + "'")
...@@ -110,6 +124,34 @@ func CheckAddress(addr string) (e error) { ...@@ -110,6 +124,34 @@ func CheckAddress(addr string) (e error) {
e = errors.New("Address Checksum error") e = errors.New("Address Checksum error")
} }
} }
if dec[0] != ver {
e = errVersion
}
return e
}
//CheckMultiSignAddress 检查多重签名地址的有效性
func CheckMultiSignAddress(addr string) (e error) {
if value, ok := multiCheckAddressCache.Get(addr); ok {
if value == nil {
return nil
}
return value.(error)
}
e = checkAddress(MultiSignVer, addr)
multiCheckAddressCache.Add(addr, e)
return
}
//CheckAddress 检查地址
func CheckAddress(addr string) (e error) {
if value, ok := checkAddressCache.Get(addr); ok {
if value == nil {
return nil
}
return value.(error)
}
e = checkAddress(NormalVer, addr)
checkAddressCache.Add(addr, e) checkAddressCache.Add(addr, e)
return return
} }
......
...@@ -12,27 +12,42 @@ import ( ...@@ -12,27 +12,42 @@ import (
"time" "time"
"github.com/33cn/chain33/common/crypto" "github.com/33cn/chain33/common/crypto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
_ "github.com/33cn/chain33/system/crypto/init" _ "github.com/33cn/chain33/system/crypto/init"
) )
func TestAddress(t *testing.T) { func genkey() crypto.PrivKey {
c, err := crypto.New("secp256k1") c, err := crypto.New("secp256k1")
if err != nil { if err != nil {
t.Error(err) panic(err)
return
} }
key, err := c.GenKey() key, err := c.GenKey()
if err != nil { if err != nil {
t.Error(err) panic(err)
return
} }
return key
}
func TestAddress(t *testing.T) {
key := genkey()
t.Logf("%X", key.Bytes()) t.Logf("%X", key.Bytes())
addr := PubKeyToAddress(key.PubKey().Bytes()) addr := PubKeyToAddress(key.PubKey().Bytes())
t.Log(addr) t.Log(addr)
} }
func TestMultiSignAddress(t *testing.T) {
key := genkey()
addr1 := MultiSignAddress(key.PubKey().Bytes())
addr := MultiSignAddress(key.PubKey().Bytes())
assert.Equal(t, addr1, addr)
err := CheckAddress(addr)
assert.Equal(t, errVersion, err)
err = CheckMultiSignAddress(addr)
assert.Nil(t, err)
t.Log(addr)
}
func TestPubkeyToAddress(t *testing.T) { func TestPubkeyToAddress(t *testing.T) {
pubkey := "024a17b0c6eb3143839482faa7e917c9b90a8cfe5008dff748789b8cea1a3d08d5" pubkey := "024a17b0c6eb3143839482faa7e917c9b90a8cfe5008dff748789b8cea1a3d08d5"
b, err := hex.DecodeString(pubkey) b, err := hex.DecodeString(pubkey)
...@@ -61,6 +76,14 @@ func TestCheckAddress(t *testing.T) { ...@@ -61,6 +76,14 @@ func TestCheckAddress(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
} }
func TestExecAddress(t *testing.T) {
assert.Equal(t, "16htvcBNSEA7fZhAdLJphDwQRQJaHpyHTp", ExecAddress("ticket"))
assert.Equal(t, "16htvcBNSEA7fZhAdLJphDwQRQJaHpyHTp", ExecAddress("ticket"))
addr, err := NewAddrFromString(ExecAddress("ticket"))
assert.Nil(t, err)
assert.Equal(t, addr.Version, NormalVer)
}
func BenchmarkExecAddress(b *testing.B) { func BenchmarkExecAddress(b *testing.B) {
start := time.Now().UnixNano() / 1000000 start := time.Now().UnixNano() / 1000000
fmt.Println(start) fmt.Println(start)
......
...@@ -47,6 +47,9 @@ func (c *channelClient) CreateRawTransaction(param *types.CreateTx) ([]byte, err ...@@ -47,6 +47,9 @@ func (c *channelClient) CreateRawTransaction(param *types.CreateTx) ([]byte, err
if param.IsToken { if param.IsToken {
execer = types.ExecName("token") execer = types.ExecName("token")
} }
if param.Execer != "" {
execer = param.Execer
}
return types.CallCreateTx(execer, "", param) return types.CallCreateTx(execer, "", param)
} }
......
...@@ -88,23 +88,6 @@ func testCreateRawTransactionCoinTransfer(t *testing.T) { ...@@ -88,23 +88,6 @@ func testCreateRawTransactionCoinTransfer(t *testing.T) {
Note: []byte("note"), Note: []byte("note"),
} }
//v := &cty.CoinsAction_Transfer{
// Transfer:&cty.CoinsTransfer{
// Amount:ctx.Amount,
// Note:ctx.To,
// },
//}
//transfer := &cty.CoinsAction{
// Value:v,
// Ty:cty.CoinsActionTransfer,
//}
//
//tx := &types.Transaction{
// Execer:[]byte("coins"),
// Payload:types.Encode(transfer),
// To:ctx.To,
//}
client := newTestChannelClient() client := newTestChannelClient()
txHex, err := client.CreateRawTransaction(&ctx) txHex, err := client.CreateRawTransaction(&ctx)
assert.Nil(t, err) assert.Nil(t, err)
......
...@@ -38,7 +38,8 @@ func (g *Grpc) CreateRawTransaction(ctx context.Context, in *pb.CreateTx) (*pb.U ...@@ -38,7 +38,8 @@ func (g *Grpc) CreateRawTransaction(ctx context.Context, in *pb.CreateTx) (*pb.U
// CreateTransaction create transaction of grpc // CreateTransaction create transaction of grpc
func (g *Grpc) CreateTransaction(ctx context.Context, in *pb.CreateTxIn) (*pb.UnsignTx, error) { func (g *Grpc) CreateTransaction(ctx context.Context, in *pb.CreateTxIn) (*pb.UnsignTx, error) {
exec := pb.LoadExecutorType(string(in.Execer)) execer := pb.ExecName(string(in.Execer))
exec := pb.LoadExecutorType(execer)
if exec == nil { if exec == nil {
log.Error("callExecNewTx", "Error", "exec not found") log.Error("callExecNewTx", "Error", "exec not found")
return nil, pb.ErrNotSupport return nil, pb.ErrNotSupport
...@@ -52,7 +53,7 @@ func (g *Grpc) CreateTransaction(ctx context.Context, in *pb.CreateTxIn) (*pb.Un ...@@ -52,7 +53,7 @@ func (g *Grpc) CreateTransaction(ctx context.Context, in *pb.CreateTxIn) (*pb.Un
if err != nil { if err != nil {
return nil, err return nil, err
} }
reply, err := pb.CallCreateTx(string(in.Execer), in.ActionName, msg) reply, err := pb.CallCreateTx(execer, in.ActionName, msg)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -344,6 +345,11 @@ func (g *Grpc) GetBlockByHashes(ctx context.Context, in *pb.ReqHashes) (*pb.Bloc ...@@ -344,6 +345,11 @@ func (g *Grpc) GetBlockByHashes(ctx context.Context, in *pb.ReqHashes) (*pb.Bloc
return g.cli.GetBlockByHashes(in) return g.cli.GetBlockByHashes(in)
} }
// GetSequenceByHash get block sequece by hash
func (g *Grpc) GetSequenceByHash(ctx context.Context, in *pb.ReqHash) (*pb.Int64, error) {
return g.cli.GetSequenceByHash(in)
}
// SignRawTx signature rawtransaction // SignRawTx signature rawtransaction
func (g *Grpc) SignRawTx(ctx context.Context, in *pb.ReqSignRawTx) (*pb.ReplySignRawTx, error) { func (g *Grpc) SignRawTx(ctx context.Context, in *pb.ReqSignRawTx) (*pb.ReplySignRawTx, error) {
return g.cli.SignRawTx(in) return g.cli.SignRawTx(in)
......
...@@ -20,12 +20,26 @@ import ( ...@@ -20,12 +20,26 @@ import (
) )
// CreateRawTransaction create rawtransaction by jrpc // CreateRawTransaction create rawtransaction by jrpc
func (c *Chain33) CreateRawTransaction(in *types.CreateTx, result *interface{}) error { func (c *Chain33) CreateRawTransaction(in *rpctypes.CreateTx, result *interface{}) error {
reply, err := c.cli.CreateRawTransaction(in) if in == nil {
log.Error("CreateRawTransaction", "Error", types.ErrInvalidParam)
return types.ErrInvalidParam
}
inpb := &types.CreateTx{
To: in.To,
Amount: in.Amount,
Fee: in.Fee,
Note: []byte(in.Note),
IsWithdraw: in.IsWithdraw,
IsToken: in.IsToken,
TokenSymbol: in.TokenSymbol,
ExecName: in.ExecName,
Execer: in.Execer,
}
reply, err := c.cli.CreateRawTransaction(inpb)
if err != nil { if err != nil {
return err return err
} }
*result = hex.EncodeToString(reply) *result = hex.EncodeToString(reply)
return nil return nil
} }
...@@ -404,50 +418,6 @@ func (c *Chain33) ImportPrivkey(in types.ReqWalletImportPrivkey, result *interfa ...@@ -404,50 +418,6 @@ func (c *Chain33) ImportPrivkey(in types.ReqWalletImportPrivkey, result *interfa
// SendToAddress send to address of coins // SendToAddress send to address of coins
func (c *Chain33) SendToAddress(in types.ReqWalletSendToAddress, result *interface{}) error { func (c *Chain33) SendToAddress(in types.ReqWalletSendToAddress, result *interface{}) error {
log.Debug("Rpc SendToAddress", "Tx", in)
if types.IsPara() {
createTx := &types.CreateTx{
To: in.GetTo(),
Amount: in.GetAmount(),
Fee: 1e5,
Note: in.GetNote(),
IsWithdraw: false,
IsToken: true,
TokenSymbol: in.GetTokenSymbol(),
ExecName: types.ExecName("token"),
}
tx, err := c.cli.CreateRawTransaction(createTx)
if err != nil {
log.Debug("ParaChain CreateRawTransaction", "Error", err.Error())
return err
}
//不需要自己去导出私钥,signRawTx 里面只需带入公钥地址,也回优先去查出相应的私钥,前提是私钥已经导入
reqSignRawTx := &types.ReqSignRawTx{
Addr: in.From,
Privkey: "",
TxHex: hex.EncodeToString(tx),
Expire: "300s",
Index: 0,
Token: "",
}
replySignRawTx, err := c.cli.SignRawTx(reqSignRawTx)
if err != nil {
log.Debug("ParaChain SignRawTx", "Error", err.Error())
return err
}
rawParm := rpctypes.RawParm{
Token: "",
Data: replySignRawTx.GetTxHex(),
}
var txHash interface{}
err = forwardTranToMainNet(rawParm, &txHash)
if err != nil {
log.Debug("ParaChain forwardTranToMainNet", "Error", err.Error())
return err
}
*result = &rpctypes.ReplyHash{Hash: txHash.(string)}
return nil
}
reply, err := c.cli.WalletSendToAddress(&in) reply, err := c.cli.WalletSendToAddress(&in)
if err != nil { if err != nil {
log.Debug("SendToAddress", "Error", err.Error()) log.Debug("SendToAddress", "Error", err.Error())
...@@ -1120,7 +1090,7 @@ func (c *Chain33) CreateTransaction(in *rpctypes.CreateTxIn, result *interface{} ...@@ -1120,7 +1090,7 @@ func (c *Chain33) CreateTransaction(in *rpctypes.CreateTxIn, result *interface{}
if in == nil { if in == nil {
return types.ErrInvalidParam return types.ErrInvalidParam
} }
btx, err := types.CallCreateTxJSON(in.Execer, in.ActionName, in.Payload) btx, err := types.CallCreateTxJSON(types.ExecName(in.Execer), in.ActionName, in.Payload)
if err != nil { if err != nil {
return err return err
} }
......
...@@ -387,11 +387,11 @@ func TestChain33_CreateRawTransaction(t *testing.T) { ...@@ -387,11 +387,11 @@ func TestChain33_CreateRawTransaction(t *testing.T) {
assert.Nil(t, testResult) assert.Nil(t, testResult)
assert.NotNil(t, err) assert.NotNil(t, err)
tx := &types.CreateTx{ tx := &rpctypes.CreateTx{
To: "qew", To: "184wj4nsgVxKyz2NhM3Yb5RK5Ap6AFRFq2",
Amount: 10, Amount: 10,
Fee: 1, Fee: 1,
Note: []byte("12312"), Note: "12312",
IsWithdraw: false, IsWithdraw: false,
IsToken: false, IsToken: false,
TokenSymbol: "", TokenSymbol: "",
......
...@@ -5,10 +5,10 @@ ...@@ -5,10 +5,10 @@
package rpc_test package rpc_test
import ( import (
"fmt"
"testing" "testing"
"github.com/33cn/chain33/common" "github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/rpc/jsonclient" "github.com/33cn/chain33/rpc/jsonclient"
rpctypes "github.com/33cn/chain33/rpc/types" rpctypes "github.com/33cn/chain33/rpc/types"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
...@@ -19,16 +19,18 @@ import ( ...@@ -19,16 +19,18 @@ import (
_ "github.com/33cn/chain33/system" _ "github.com/33cn/chain33/system"
) )
func getRPCClient(t *testing.T, mocker *testnode.Chain33Mock) *jsonclient.JSONClient {
jrpcClient := mocker.GetJSONC()
assert.NotNil(t, jrpcClient)
return jrpcClient
}
func TestErrLog(t *testing.T) { func TestErrLog(t *testing.T) {
// 启动RPCmocker // 启动RPCmocker
mocker := testnode.New("--free--", nil) mocker := testnode.New("--free--", nil)
defer mocker.Close() defer mocker.Close()
mocker.Listen() mocker.Listen()
jrpcClient := getRPCClient(t, mocker)
rpcCfg := mocker.GetCfg().RPC
jrpcClient, err := jsonclient.NewJSONClient(fmt.Sprintf("http://%s/", rpcCfg.JrpcBindAddr))
assert.NoError(t, err)
assert.NotNil(t, jrpcClient)
gen := mocker.GetGenesisKey() gen := mocker.GetGenesisKey()
//发送交易到区块链 //发送交易到区块链
addr1, key1 := util.Genaddress() addr1, key1 := util.Genaddress()
...@@ -55,3 +57,43 @@ func TestErrLog(t *testing.T) { ...@@ -55,3 +57,43 @@ func TestErrLog(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, string(testResult.Receipt.Logs[0].Log), `"ErrNoBalance"`) assert.Equal(t, string(testResult.Receipt.Logs[0].Log), `"ErrNoBalance"`)
} }
func getTx(t *testing.T, hex string) *types.Transaction {
data, err := common.FromHex(hex)
assert.Nil(t, err)
var tx types.Transaction
err = types.Decode(data, &tx)
assert.Nil(t, err)
return &tx
}
func TestSendToExec(t *testing.T) {
mocker := testnode.New("--free--", nil)
defer mocker.Close()
mocker.Listen()
jrpcClient := getRPCClient(t, mocker)
//1. 调用createrawtransaction 创建交易
req := &rpctypes.CreateTx{
To: address.ExecAddress("user.f3d"),
Amount: 10,
Fee: 1,
Note: "12312",
IsWithdraw: false,
IsToken: false,
TokenSymbol: "",
ExecName: "user.f3d",
}
var res string
err := jrpcClient.Call("Chain33.CreateRawTransaction", req, &res)
assert.Nil(t, err)
gen := mocker.GetGenesisKey()
tx := getTx(t, res)
tx.Sign(types.SECP256K1, gen)
reply, err := mocker.GetAPI().SendTx(tx)
assert.Nil(t, err)
_, err = mocker.WaitTx(reply.GetMsg())
assert.Nil(t, err)
block := mocker.GetLastBlock()
balance := mocker.GetExecAccount(block.StateHash, "user.f3d", mocker.GetGenesisAddress()).Balance
assert.Equal(t, int64(10), balance)
}
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package rpc package rpc
import ( import (
"encoding/hex"
"errors" "errors"
"testing" "testing"
"time" "time"
...@@ -114,10 +115,33 @@ func TestJSONClient_Call(t *testing.T) { ...@@ -114,10 +115,33 @@ func TestJSONClient_Call(t *testing.T) {
err = jsonClient.Call("Chain33.IsNtpClockSync", &types.ReqNil{}, &retNtp) err = jsonClient.Call("Chain33.IsNtpClockSync", &types.ReqNil{}, &retNtp)
assert.Nil(t, err) assert.Nil(t, err)
assert.True(t, retNtp) assert.True(t, retNtp)
testCreateTxCoins(t, jsonClient)
server.Close() server.Close()
mock.AssertExpectationsForObjects(t, api) mock.AssertExpectationsForObjects(t, api)
} }
func testCreateTxCoins(t *testing.T, jsonClient *jsonclient.JSONClient) {
req := &rpctypes.CreateTx{
To: "184wj4nsgVxKyz2NhM3Yb5RK5Ap6AFRFq2",
Amount: 10,
Fee: 1,
Note: "12312",
IsWithdraw: false,
IsToken: false,
TokenSymbol: "",
ExecName: types.ExecName("coins"),
}
var res string
err := jsonClient.Call("Chain33.CreateRawTransaction", req, &res)
assert.Nil(t, err)
txbytes, err := hex.DecodeString(res)
assert.Nil(t, err)
var tx types.Transaction
err = types.Decode(txbytes, &tx)
assert.Nil(t, err)
assert.Equal(t, "184wj4nsgVxKyz2NhM3Yb5RK5Ap6AFRFq2", tx.To)
}
func TestGrpc_Call(t *testing.T) { func TestGrpc_Call(t *testing.T) {
rpcCfg = new(types.RPC) rpcCfg = new(types.RPC)
rpcCfg.GrpcBindAddr = "127.0.0.1:8101" rpcCfg.GrpcBindAddr = "127.0.0.1:8101"
......
...@@ -360,3 +360,16 @@ type ExecAccount struct { ...@@ -360,3 +360,16 @@ type ExecAccount struct {
type ExecNameParm struct { type ExecNameParm struct {
ExecName string `json:"execname"` ExecName string `json:"execname"`
} }
//CreateTx 为了简化Note 的创建过程,在json rpc 中,note 采用string 格式
type CreateTx struct {
To string `json:"to,omitempty"`
Amount int64 `json:"amount,omitempty"`
Fee int64 `json:"fee,omitempty"`
Note string `json:"note,omitempty"`
IsWithdraw bool `json:"isWithdraw,omitempty"`
IsToken bool `json:"isToken,omitempty"`
TokenSymbol string `json:"tokenSymbol,omitempty"`
ExecName string `json:"execName,omitempty"` //TransferToExec and Withdraw 的执行器
Execer string `json:"execer,omitempty"` //执行器名称
}
...@@ -337,6 +337,10 @@ func buildHashList(deltx []*types.Transaction) *types.TxHashList { ...@@ -337,6 +337,10 @@ func buildHashList(deltx []*types.Transaction) *types.TxHashList {
//WriteBlock 向blockchain写区块 //WriteBlock 向blockchain写区块
func (bc *BaseClient) WriteBlock(prev []byte, block *types.Block) error { func (bc *BaseClient) WriteBlock(prev []byte, block *types.Block) error {
//保存block的原始信息用于删除mempool中的错误交易
rawtxs := make([]*types.Transaction, len(block.Txs))
copy(rawtxs, block.Txs)
blockdetail := &types.BlockDetail{Block: block} blockdetail := &types.BlockDetail{Block: block}
msg := bc.client.NewMessage("blockchain", types.EventAddBlockDetail, blockdetail) msg := bc.client.NewMessage("blockchain", types.EventAddBlockDetail, blockdetail)
bc.client.Send(msg, true) bc.client.Send(msg, true)
...@@ -346,7 +350,7 @@ func (bc *BaseClient) WriteBlock(prev []byte, block *types.Block) error { ...@@ -346,7 +350,7 @@ func (bc *BaseClient) WriteBlock(prev []byte, block *types.Block) error {
} }
blockdetail = resp.GetData().(*types.BlockDetail) blockdetail = resp.GetData().(*types.BlockDetail)
//从mempool 中删除错误的交易 //从mempool 中删除错误的交易
deltx := diffTx(block.Txs, blockdetail.Block.Txs) deltx := diffTx(rawtxs, blockdetail.Block.Txs)
if len(deltx) > 0 { if len(deltx) > 0 {
bc.delMempoolTx(deltx) bc.delMempoolTx(deltx)
} }
......
...@@ -64,18 +64,19 @@ type Mempool struct { ...@@ -64,18 +64,19 @@ type Mempool struct {
// Consensus 配置 // Consensus 配置
type Consensus struct { type Consensus struct {
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
GenesisBlockTime int64 `protobuf:"varint,2,opt,name=genesisBlockTime" json:"genesisBlockTime,omitempty"` GenesisBlockTime int64 `protobuf:"varint,2,opt,name=genesisBlockTime" json:"genesisBlockTime,omitempty"`
Minerstart bool `protobuf:"varint,3,opt,name=minerstart" json:"minerstart,omitempty"` Minerstart bool `protobuf:"varint,3,opt,name=minerstart" json:"minerstart,omitempty"`
Genesis string `protobuf:"bytes,4,opt,name=genesis" json:"genesis,omitempty"` Genesis string `protobuf:"bytes,4,opt,name=genesis" json:"genesis,omitempty"`
HotkeyAddr string `protobuf:"bytes,5,opt,name=hotkeyAddr" json:"hotkeyAddr,omitempty"` HotkeyAddr string `protobuf:"bytes,5,opt,name=hotkeyAddr" json:"hotkeyAddr,omitempty"`
ForceMining bool `protobuf:"varint,6,opt,name=forceMining" json:"forceMining,omitempty"` ForceMining bool `protobuf:"varint,6,opt,name=forceMining" json:"forceMining,omitempty"`
WriteBlockSeconds int64 `protobuf:"varint,20,opt,name=writeBlockSeconds" json:"writeBlockSeconds,omitempty"` WriteBlockSeconds int64 `protobuf:"varint,20,opt,name=writeBlockSeconds" json:"writeBlockSeconds,omitempty"`
ParaRemoteGrpcClient string `protobuf:"bytes,22,opt,name=paraRemoteGrpcClient" json:"paraRemoteGrpcClient,omitempty"` ParaRemoteGrpcClient string `protobuf:"bytes,22,opt,name=paraRemoteGrpcClient" json:"paraRemoteGrpcClient,omitempty"`
StartHeight int64 `protobuf:"varint,23,opt,name=startHeight" json:"startHeight,omitempty"` StartHeight int64 `protobuf:"varint,23,opt,name=startHeight" json:"startHeight,omitempty"`
EmptyBlockInterval int64 `protobuf:"varint,24,opt,name=emptyBlockInterval" json:"emptyBlockInterval,omitempty"` EmptyBlockInterval int64 `protobuf:"varint,24,opt,name=emptyBlockInterval" json:"emptyBlockInterval,omitempty"`
AuthAccount string `protobuf:"bytes,25,opt,name=authAccount" json:"authAccount,omitempty"` AuthAccount string `protobuf:"bytes,25,opt,name=authAccount" json:"authAccount,omitempty"`
WaitBlocks4CommitMsg int32 `protobuf:"varint,26,opt,name=waitBlocks4CommitMsg" json:"waitBlocks4CommitMsg,omitempty"` WaitBlocks4CommitMsg int32 `protobuf:"varint,26,opt,name=waitBlocks4CommitMsg" json:"waitBlocks4CommitMsg,omitempty"`
SearchHashMatchedBlockDepth int32 `protobuf:"varint,27,opt,name=searchHashMatchedBlockDepth" json:"searchHashMatchedBlockDepth,omitempty"`
} }
// Wallet 配置 // Wallet 配置
......
...@@ -225,6 +225,13 @@ func S(key string, value interface{}) { ...@@ -225,6 +225,13 @@ func S(key string, value interface{}) {
setChainConfig(key, value) setChainConfig(key, value)
} }
//SetTitleOnlyForTest set title only for test use
func SetTitleOnlyForTest(ti string) {
mu.Lock()
defer mu.Unlock()
title = ti
}
// Init 初始化 // Init 初始化
func Init(t string, cfg *Config) { func Init(t string, cfg *Config) {
mu.Lock() mu.Lock()
...@@ -303,7 +310,6 @@ func SetMinFee(fee int64) { ...@@ -303,7 +310,6 @@ func SetMinFee(fee int64) {
} }
func isPara() bool { func isPara() bool {
//user.p.guodun.
return strings.Count(title, ".") == 3 && strings.HasPrefix(title, ParaKeyX) return strings.Count(title, ".") == 3 && strings.HasPrefix(title, ParaKeyX)
} }
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
) )
var slash = []byte("-") var slash = []byte("-")
var sharp = []byte("#")
//Debug 调试开关 //Debug 调试开关
var Debug = false var Debug = false
......
...@@ -109,8 +109,8 @@ func CallExecNewTx(execName, action string, param interface{}) ([]byte, error) { ...@@ -109,8 +109,8 @@ func CallExecNewTx(execName, action string, param interface{}) ([]byte, error) {
return FormatTxEncode(execName, tx) return FormatTxEncode(execName, tx)
} }
// CallCreateTx 构造交易信息 //CallCreateTransaction 创建一个交易
func CallCreateTx(execName, action string, param Message) ([]byte, error) { func CallCreateTransaction(execName, action string, param Message) (*Transaction, error) {
exec := LoadExecutorType(execName) exec := LoadExecutorType(execName)
if exec == nil { if exec == nil {
tlog.Error("CallCreateTx", "Error", "exec not found") tlog.Error("CallCreateTx", "Error", "exec not found")
...@@ -121,9 +121,13 @@ func CallCreateTx(execName, action string, param Message) ([]byte, error) { ...@@ -121,9 +121,13 @@ func CallCreateTx(execName, action string, param Message) ([]byte, error) {
tlog.Error("CallCreateTx", "Error", "param in nil") tlog.Error("CallCreateTx", "Error", "param in nil")
return nil, ErrInvalidParam return nil, ErrInvalidParam
} }
tx, err := exec.Create(action, param) return exec.Create(action, param)
}
// CallCreateTx 构造交易信息
func CallCreateTx(execName, action string, param Message) ([]byte, error) {
tx, err := CallCreateTransaction(execName, action, param)
if err != nil { if err != nil {
tlog.Error("CallCreateTx", "Error", err)
return nil, err return nil, err
} }
return FormatTxEncode(execName, tx) return FormatTxEncode(execName, tx)
......
...@@ -132,5 +132,4 @@ func TestCallCreateTx(t *testing.T) { ...@@ -132,5 +132,4 @@ func TestCallCreateTx(t *testing.T) {
assert.Equal(t, tx.Execer, []byte("manage")) assert.Equal(t, tx.Execer, []byte("manage"))
fee, _ = tx.GetRealFee(GInt("MinFee")) fee, _ = tx.GetRealFee(GInt("MinFee"))
assert.Equal(t, tx.Fee, fee) assert.Equal(t, tx.Fee, fee)
} }
...@@ -762,6 +762,36 @@ func (_m *Chain33Client) GetSeed(ctx context.Context, in *types.GetSeedByPw, opt ...@@ -762,6 +762,36 @@ func (_m *Chain33Client) GetSeed(ctx context.Context, in *types.GetSeedByPw, opt
return r0, r1 return r0, r1
} }
// GetSequenceByHash provides a mock function with given fields: ctx, in, opts
func (_m *Chain33Client) GetSequenceByHash(ctx context.Context, in *types.ReqHash, opts ...grpc.CallOption) (*types.Int64, 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.Int64
if rf, ok := ret.Get(0).(func(context.Context, *types.ReqHash, ...grpc.CallOption) *types.Int64); ok {
r0 = rf(ctx, in, opts...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.Int64)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *types.ReqHash, ...grpc.CallOption) error); ok {
r1 = rf(ctx, in, opts...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetTransactionByAddr provides a mock function with given fields: ctx, in, opts // GetTransactionByAddr provides a mock function with given fields: ctx, in, opts
func (_m *Chain33Client) GetTransactionByAddr(ctx context.Context, in *types.ReqAddr, opts ...grpc.CallOption) (*types.ReplyTxInfos, error) { func (_m *Chain33Client) GetTransactionByAddr(ctx context.Context, in *types.ReqAddr, opts ...grpc.CallOption) (*types.ReplyTxInfos, error) {
_va := make([]interface{}, len(opts)) _va := make([]interface{}, len(opts))
......
...@@ -125,6 +125,9 @@ service chain33 { ...@@ -125,6 +125,9 @@ service chain33 {
//获取指定区间的block加载序列号信息 //获取指定区间的block加载序列号信息
rpc GetBlockSequences(ReqBlocks) returns (BlockSequences) {} rpc GetBlockSequences(ReqBlocks) returns (BlockSequences) {}
//get add block's sequence by hash
rpc GetSequenceByHash(ReqHash) returns (Int64) {}
//通过block hash 获取对应的blocks信息 //通过block hash 获取对应的blocks信息
rpc GetBlockByHashes(ReqHashes) returns (BlockDetails) {} rpc GetBlockByHashes(ReqHashes) returns (BlockDetails) {}
//关闭chain33 //关闭chain33
......
...@@ -49,6 +49,7 @@ message CreateTx { ...@@ -49,6 +49,7 @@ message CreateTx {
bool isToken = 6; bool isToken = 6;
string tokenSymbol = 7; string tokenSymbol = 7;
string execName = 8; string execName = 8;
string execer = 9;
} }
message CreateTransactionGroup { message CreateTransactionGroup {
......
...@@ -41,6 +41,9 @@ type TxGroup interface { ...@@ -41,6 +41,9 @@ type TxGroup interface {
//ExecName 执行器name //ExecName 执行器name
func ExecName(name string) string { func ExecName(name string) string {
if len(name) > 1 && name[0] == '#' {
return name[1:]
}
if IsParaExecName(name) { if IsParaExecName(name) {
return name return name
} }
...@@ -61,7 +64,7 @@ func IsAllowExecName(name []byte, execer []byte) bool { ...@@ -61,7 +64,7 @@ func IsAllowExecName(name []byte, execer []byte) bool {
return false return false
} }
// name中不允许有 "-" // name中不允许有 "-"
if bytes.Contains(name, slash) { if bytes.Contains(name, slash) || bytes.Contains(name, sharp) {
return false return false
} }
if !bytes.Equal(name, execer) && !bytes.Equal(name, GetRealExecName(execer)) { if !bytes.Equal(name, execer) && !bytes.Equal(name, GetRealExecName(execer)) {
......
...@@ -5,5 +5,48 @@ ...@@ -5,5 +5,48 @@
package types_test package types_test
import ( import (
"testing"
"github.com/33cn/chain33/common/address"
_ "github.com/33cn/chain33/system" _ "github.com/33cn/chain33/system"
"github.com/33cn/chain33/types"
"github.com/stretchr/testify/assert"
) )
//how to create transafer for para
func TestCallCreateTxPara(t *testing.T) {
ti := types.GetTitle()
defer types.SetTitleOnlyForTest(ti)
types.SetTitleOnlyForTest("user.p.sto.")
req := &types.CreateTx{
To: "184wj4nsgVxKyz2NhM3Yb5RK5Ap6AFRFq2",
Amount: 10,
Fee: 1,
Note: []byte("12312"),
IsWithdraw: false,
IsToken: false,
TokenSymbol: "",
ExecName: types.ExecName("coins"),
}
assert.True(t, types.IsPara())
tx, err := types.CallCreateTransaction("coins", "", req)
assert.Nil(t, err)
tx, err = types.FormatTx("coins", tx)
assert.Nil(t, err)
assert.Equal(t, "coins", string(tx.Execer))
assert.Equal(t, address.ExecAddress("coins"), tx.To)
tx, err = types.FormatTx(types.ExecName("coins"), tx)
assert.Nil(t, err)
assert.Equal(t, "user.p.sto.coins", string(tx.Execer))
assert.Equal(t, address.ExecAddress("user.p.sto.coins"), tx.To)
}
func TestExecName(t *testing.T) {
assert.Equal(t, types.ExecName("coins"), "coins")
ti := types.GetTitle()
defer types.SetTitleOnlyForTest(ti)
types.SetTitleOnlyForTest("user.p.sto.")
assert.Equal(t, types.ExecName("coins"), "user.p.sto.coins")
//#在exec前面加一个 # 表示不重写执行器
assert.Equal(t, types.ExecName("#coins"), "coins")
}
...@@ -46,6 +46,12 @@ func TestAllowExecName(t *testing.T) { ...@@ -46,6 +46,12 @@ func TestAllowExecName(t *testing.T) {
isok = IsAllowExecName([]byte("coins"), []byte("user.p.guodun.user.coins")) isok = IsAllowExecName([]byte("coins"), []byte("user.p.guodun.user.coins"))
assert.Equal(t, isok, true) assert.Equal(t, isok, true)
isok = IsAllowExecName([]byte("#coins"), []byte("user.p.guodun.user.coins"))
assert.Equal(t, isok, false)
isok = IsAllowExecName([]byte("coins-"), []byte("user.p.guodun.user.coins"))
assert.Equal(t, isok, false)
} }
func BenchmarkExecName(b *testing.B) { func BenchmarkExecName(b *testing.B) {
......
...@@ -329,6 +329,14 @@ func (mock *Chain33Mock) GetAccount(stateHash []byte, addr string) *types.Accoun ...@@ -329,6 +329,14 @@ func (mock *Chain33Mock) GetAccount(stateHash []byte, addr string) *types.Accoun
return acc.LoadAccount(addr) return acc.LoadAccount(addr)
} }
//GetExecAccount :get execer account info
func (mock *Chain33Mock) GetExecAccount(stateHash []byte, execer, addr string) *types.Account {
statedb := executor.NewStateDB(mock.client, stateHash, nil, nil)
acc := account.NewCoinsAccount()
acc.SetDB(statedb)
return acc.LoadExecAccount(addr, address.ExecAddress(execer))
}
//GetBlock : //GetBlock :
func (mock *Chain33Mock) GetBlock(height int64) *types.Block { func (mock *Chain33Mock) GetBlock(height int64) *types.Block {
blocks, err := mock.api.GetBlocks(&types.ReqBlocks{Start: height, End: height}) blocks, err := mock.api.GetBlocks(&types.ReqBlocks{Start: height, End: height})
......
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