Commit 44cfc785 authored by kingwang's avatar kingwang Committed by vipwzw

update chain33 05/17

parent 5fd58c21
...@@ -437,10 +437,16 @@ func (bs *BlockStore) LoadBlockByHeight(height int64) (*types.BlockDetail, error ...@@ -437,10 +437,16 @@ func (bs *BlockStore) LoadBlockByHeight(height int64) (*types.BlockDetail, error
//LoadBlockByHash 通过hash获取BlockDetail信息 //LoadBlockByHash 通过hash获取BlockDetail信息
func (bs *BlockStore) LoadBlockByHash(hash []byte) (*types.BlockDetail, error) { func (bs *BlockStore) LoadBlockByHash(hash []byte) (*types.BlockDetail, error) {
block, _, err := bs.loadBlockByHash(hash)
return block, err
}
func (bs *BlockStore) loadBlockByHash(hash []byte) (*types.BlockDetail, int, error) {
var blockdetail types.BlockDetail var blockdetail types.BlockDetail
var blockheader types.Header var blockheader types.Header
var blockbody types.BlockBody var blockbody types.BlockBody
var block types.Block var block types.Block
var blockSize int
//通过hash获取blockheader //通过hash获取blockheader
header, err := bs.db.Get(calcHashToBlockHeaderKey(hash)) header, err := bs.db.Get(calcHashToBlockHeaderKey(hash))
...@@ -448,26 +454,30 @@ func (bs *BlockStore) LoadBlockByHash(hash []byte) (*types.BlockDetail, error) { ...@@ -448,26 +454,30 @@ func (bs *BlockStore) LoadBlockByHash(hash []byte) (*types.BlockDetail, error) {
if err != dbm.ErrNotFoundInDb { if err != dbm.ErrNotFoundInDb {
storeLog.Error("LoadBlockByHash calcHashToBlockHeaderKey", "hash", common.ToHex(hash), "err", err) storeLog.Error("LoadBlockByHash calcHashToBlockHeaderKey", "hash", common.ToHex(hash), "err", err)
} }
return nil, types.ErrHashNotExist return nil, blockSize, types.ErrHashNotExist
} }
err = proto.Unmarshal(header, &blockheader) err = proto.Unmarshal(header, &blockheader)
if err != nil { if err != nil {
storeLog.Error("LoadBlockByHash", "err", err) storeLog.Error("LoadBlockByHash", "err", err)
return nil, err return nil, blockSize, err
} }
blockSize += len(header)
//通过hash获取blockbody //通过hash获取blockbody
body, err := bs.db.Get(calcHashToBlockBodyKey(hash)) body, err := bs.db.Get(calcHashToBlockBodyKey(hash))
if body == nil || err != nil { if body == nil || err != nil {
if err != dbm.ErrNotFoundInDb { if err != dbm.ErrNotFoundInDb {
storeLog.Error("LoadBlockByHash calcHashToBlockBodyKey ", "err", err) storeLog.Error("LoadBlockByHash calcHashToBlockBodyKey ", "err", err)
} }
return nil, types.ErrHashNotExist return nil, blockSize, types.ErrHashNotExist
} }
err = proto.Unmarshal(body, &blockbody) err = proto.Unmarshal(body, &blockbody)
if err != nil { if err != nil {
storeLog.Error("LoadBlockByHash", "err", err) storeLog.Error("LoadBlockByHash", "err", err)
return nil, err return nil, blockSize, err
} }
blockSize += len(body)
block.Version = blockheader.Version block.Version = blockheader.Version
block.ParentHash = blockheader.ParentHash block.ParentHash = blockheader.ParentHash
block.TxHash = blockheader.TxHash block.TxHash = blockheader.TxHash
...@@ -485,7 +495,7 @@ func (bs *BlockStore) LoadBlockByHash(hash []byte) (*types.BlockDetail, error) { ...@@ -485,7 +495,7 @@ func (bs *BlockStore) LoadBlockByHash(hash []byte) (*types.BlockDetail, error) {
//storeLog.Info("LoadBlockByHash", "Height", block.Height, "Difficulty", blockdetail.Block.Difficulty) //storeLog.Info("LoadBlockByHash", "Height", block.Height, "Difficulty", blockdetail.Block.Difficulty)
return &blockdetail, nil return &blockdetail, blockSize, nil
} }
//SaveBlock 批量保存blocks信息到db数据库中,并返回最新的sequence值 //SaveBlock 批量保存blocks信息到db数据库中,并返回最新的sequence值
...@@ -989,13 +999,13 @@ func (bs *BlockStore) saveBlockSequence(storeBatch dbm.Batch, hash []byte, heigh ...@@ -989,13 +999,13 @@ func (bs *BlockStore) saveBlockSequence(storeBatch dbm.Batch, hash []byte, heigh
} }
//LoadBlockBySequence 通过seq高度获取BlockDetail信息 //LoadBlockBySequence 通过seq高度获取BlockDetail信息
func (bs *BlockStore) LoadBlockBySequence(Sequence int64) (*types.BlockDetail, error) { func (bs *BlockStore) LoadBlockBySequence(Sequence int64) (*types.BlockDetail, int, error) {
//首先通过Sequence序列号获取对应的blockhash和操作类型从db中 //首先通过Sequence序列号获取对应的blockhash和操作类型从db中
BlockSequence, err := bs.GetBlockSequence(Sequence) BlockSequence, err := bs.GetBlockSequence(Sequence)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
return bs.LoadBlockByHash(BlockSequence.Hash) return bs.loadBlockByHash(BlockSequence.Hash)
} }
//GetBlockSequence 从db数据库中获取指定Sequence对应的block序列操作信息 //GetBlockSequence 从db数据库中获取指定Sequence对应的block序列操作信息
......
...@@ -854,7 +854,7 @@ func testLoadBlockBySequence(t *testing.T, blockchain *blockchain.BlockChain) { ...@@ -854,7 +854,7 @@ func testLoadBlockBySequence(t *testing.T, blockchain *blockchain.BlockChain) {
curheight := blockchain.GetBlockHeight() curheight := blockchain.GetBlockHeight()
lastseq, _ := blockchain.GetStore().LoadBlockLastSequence() lastseq, _ := blockchain.GetStore().LoadBlockLastSequence()
block, err := blockchain.GetStore().LoadBlockBySequence(lastseq) block, _, err := blockchain.GetStore().LoadBlockBySequence(lastseq)
require.NoError(t, err) require.NoError(t, err)
if block.Block.Height != curheight { if block.Block.Height != curheight {
......
...@@ -11,6 +11,11 @@ import ( ...@@ -11,6 +11,11 @@ import (
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
) )
const (
pushMaxSeq = 100
pushMaxSize = 100 * 1024 * 1024
)
//pushNotify push Notify //pushNotify push Notify
type pushNotify struct { type pushNotify struct {
cb chan *types.BlockSeqCB cb chan *types.BlockSeqCB
...@@ -94,10 +99,10 @@ func (p *pushseq) updateSeq(seq int64) { ...@@ -94,10 +99,10 @@ func (p *pushseq) updateSeq(seq int64) {
} }
func (p *pushseq) trigeRun(run chan struct{}, sleep time.Duration) { func (p *pushseq) trigeRun(run chan struct{}, sleep time.Duration) {
go func() {
if sleep > 0 { if sleep > 0 {
time.Sleep(sleep) time.Sleep(sleep)
} }
go func() {
select { select {
case run <- struct{}{}: case run <- struct{}{}:
default: default:
...@@ -132,9 +137,13 @@ func (p *pushseq) runTask(input pushNotify) { ...@@ -132,9 +137,13 @@ func (p *pushseq) runTask(input pushNotify) {
p.trigeRun(run, 100*time.Millisecond) p.trigeRun(run, 100*time.Millisecond)
continue continue
} }
data, err := p.getDataBySeq(lastseq + 1) seqCount := pushMaxSeq
if lastseq+int64(seqCount) > maxseq {
seqCount = 1
}
data, err := p.getSeqs(lastseq+1, seqCount, pushMaxSize)
if err != nil { if err != nil {
chainlog.Error("getDataBySeq", "err", err) chainlog.Error("getDataBySeq", "err", err, "seq", lastseq+1, "maxSeq", seqCount)
p.trigeRun(run, 1000*time.Millisecond) p.trigeRun(run, 1000*time.Millisecond)
continue continue
} }
...@@ -146,14 +155,14 @@ func (p *pushseq) runTask(input pushNotify) { ...@@ -146,14 +155,14 @@ func (p *pushseq) runTask(input pushNotify) {
continue continue
} }
//update seqid //update seqid
lastseq = lastseq + 1 lastseq = lastseq + int64(seqCount)
p.trigeRun(run, 0) p.trigeRun(run, 0)
} }
} }
}(input) }(input)
} }
func (p *pushseq) postData(cb *types.BlockSeqCB, data *types.BlockSeq) (err error) { func (p *pushseq) postData(cb *types.BlockSeqCB, data *types.BlockSeqs) (err error) {
var postdata []byte var postdata []byte
if cb.Encode == "json" { if cb.Encode == "json" {
...@@ -195,18 +204,36 @@ func (p *pushseq) postData(cb *types.BlockSeqCB, data *types.BlockSeq) (err erro ...@@ -195,18 +204,36 @@ func (p *pushseq) postData(cb *types.BlockSeqCB, data *types.BlockSeq) (err erro
chainlog.Error("postData fail", "cb.name", cb.Name, "body", string(body)) chainlog.Error("postData fail", "cb.name", cb.Name, "body", string(body))
return types.ErrPushSeqPostData return types.ErrPushSeqPostData
} }
chainlog.Debug("postData success", "cb.name", cb.Name, "SeqNum", data.Num) chainlog.Debug("postData success", "cb.name", cb.Name, "SeqNum", data.Seqs[0].Num, "seqCount", len(data.Seqs))
return p.store.setSeqCBLastNum([]byte(cb.Name), data.Num) return p.store.setSeqCBLastNum([]byte(cb.Name), data.Seqs[0].Num+int64(len(data.Seqs))-1)
} }
func (p *pushseq) getDataBySeq(seq int64) (*types.BlockSeq, error) { func (p *pushseq) getDataBySeq(seq int64) (*types.BlockSeq, int, error) {
seqdata, err := p.store.GetBlockSequence(seq) seqdata, err := p.store.GetBlockSequence(seq)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
detail, err := p.store.LoadBlockBySequence(seq) detail, blockSize, err := p.store.LoadBlockBySequence(seq)
if err != nil {
return nil, 0, err
}
return &types.BlockSeq{Num: seq, Seq: seqdata, Detail: detail}, blockSize, nil
}
func (p *pushseq) getSeqs(seq int64, seqCount, maxSize int) (*types.BlockSeqs, error) {
seqs := &types.BlockSeqs{}
totalSize := 0
for i := 0; i < seqCount; i++ {
seq, size, err := p.getDataBySeq(seq + int64(i))
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &types.BlockSeq{Num: seq, Seq: seqdata, Detail: detail}, nil if totalSize == 0 || totalSize+size < maxSize {
seqs.Seqs = append(seqs.Seqs, seq)
totalSize += size
} else {
break
}
}
return seqs, nil
} }
...@@ -351,7 +351,9 @@ function base_test() { ...@@ -351,7 +351,9 @@ function base_test() {
if [ "$DAPP" == "" ]; then if [ "$DAPP" == "" ]; then
system_test_rpc "https://${1}:8801" system_test_rpc "https://${1}:8801"
fi fi
if [ "$DAPP" == "paracross" ]; then
system_test_rpc "https://${1}:8901"
fi
} }
function dapp_run() { function dapp_run() {
if [ -e "$DAPP_TEST_FILE" ]; then if [ -e "$DAPP_TEST_FILE" ]; then
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
# shellcheck disable=SC2128 # shellcheck disable=SC2128
MAIN_HTTP="" MAIN_HTTP=""
IS_PARA=false
CASE_ERR="" CASE_ERR=""
#color #color
...@@ -13,6 +14,8 @@ NOC='\033[0m' ...@@ -13,6 +14,8 @@ NOC='\033[0m'
echo_rst() { echo_rst() {
if [ "$2" -eq 0 ]; then if [ "$2" -eq 0 ]; then
echo -e "${GRE}$1 ok${NOC}" echo -e "${GRE}$1 ok${NOC}"
elif [ "$2" -eq 2 ]; then
echo -e "${GRE}$1 not support${NOC}"
else else
echo -e "${RED}$1 fail${NOC}" echo -e "${RED}$1 fail${NOC}"
CASE_ERR="err" CASE_ERR="err"
...@@ -21,14 +24,14 @@ echo_rst() { ...@@ -21,14 +24,14 @@ echo_rst() {
} }
chain33_lock() { chain33_lock() {
ok=$(curl -k -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"Chain33.Lock","params":[]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r ".result.isOK") ok=$(curl -ksd '{"method":"Chain33.Lock","params":[]}' ${MAIN_HTTP} | jq -r ".result.isOK")
[ "$ok" == true ] [ "$ok" == true ]
rst=$? rst=$?
echo_rst "$FUNCNAME" "$rst" echo_rst "$FUNCNAME" "$rst"
} }
chain33_unlock() { chain33_unlock() {
ok=$(curl -k -s --data-binary '{"jsonrpc":"2.0","id":2,"method":"Chain33.UnLock","params":[{"passwd":"1314fuzamei","timeout":0}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r ".result.isOK") ok=$(curl -ksd '{"method":"Chain33.UnLock","params":[{"passwd":"1314fuzamei","timeout":0}]}' ${MAIN_HTTP} | jq -r ".result.isOK")
[ "$ok" == true ] [ "$ok" == true ]
rst=$? rst=$?
echo_rst "$FUNCNAME" "$rst" echo_rst "$FUNCNAME" "$rst"
...@@ -106,6 +109,9 @@ chain33_SetLabl() { ...@@ -106,6 +109,9 @@ chain33_SetLabl() {
chain33_GetPeerInfo() { chain33_GetPeerInfo() {
if [ "$IS_PARA" == true ]; then
echo_rst "$FUNCNAME" 2
else
req='"method":"Chain33.GetPeerInfo", "params":[{}]' req='"method":"Chain33.GetPeerInfo", "params":[{}]'
echo "#request: $req" echo "#request: $req"
resp=$(curl -ksd "{$req}" "$1") resp=$(curl -ksd "{$req}" "$1")
...@@ -114,6 +120,7 @@ chain33_GetPeerInfo() { ...@@ -114,6 +120,7 @@ chain33_GetPeerInfo() {
[has("addr", "port", "name", "mempoolSize", "self", "header"), true] | unique | length == 1)' <<<"$resp") [has("addr", "port", "name", "mempoolSize", "self", "header"), true] | unique | length == 1)' <<<"$resp")
[ "$ok" == true ] [ "$ok" == true ]
echo_rst "$FUNCNAME" "$?" echo_rst "$FUNCNAME" "$?"
fi
} }
chain33_GetHeaders() { chain33_GetHeaders() {
...@@ -198,33 +205,552 @@ chain33_MergeBalance() { ...@@ -198,33 +205,552 @@ chain33_MergeBalance() {
echo_rst "$FUNCNAME" "$?" echo_rst "$FUNCNAME" "$?"
} }
function system_test_rpc() { chain33_QueryTotalFee() {
local ip=$1 local height=1
MAIN_HTTP=$1 hash=$(curl -ksd '{"method":"Chain33.GetBlockHash","params":[{"height":'$height'}]}' ${MAIN_HTTP} | jq -r ".result.hash")
echo "=========== # system rpc test =============" if [ -z "$hash" ]; then
echo "ip=$MAIN_HTTP" echo "hash is null"
echo_rst "$FUNCNAME" 1
fi
prefixhash_base64=$(echo -n "TotalFeeKey:" | base64)
blockhash_base64=$(echo -n "$hash" | cut -d " " -f 1 | xxd -r -p | base64)
base64_hash="$prefixhash_base64$blockhash_base64"
# shellcheck disable=SC2086
txs=$(curl -ksd '{"method":"Chain33.QueryTotalFee","params":[{"keys":["'$base64_hash'"]}]}' ${MAIN_HTTP} | jq -r ".result.txCount")
[ "$txs" -ge 0 ]
echo_rst "$FUNCNAME" "$?"
}
chain33_GetNetInfo() {
if [ "$IS_PARA" == true ]; then
echo_rst "$FUNCNAME" 2
else
method="GetNetInfo"
addr=$(curl -ksd '{"method":"Chain33.'"$method"'","params":[]}' ${MAIN_HTTP} | jq -r ".result.externalAddr")
service=$(curl -ksd '{"method":"Chain33.GetNetInfo","params":[]}' ${MAIN_HTTP} | jq -r ".result.service")
[ "$addr" != "null" ] && [ "$service" == "true" ]
echo_rst "$FUNCNAME" "$?"
fi
}
chain33_GetFatalFailure() {
r1=$(curl -ksd '{"method":"Chain33.GetFatalFailure","params":[]}' ${MAIN_HTTP} | jq -r ".result")
error=$(curl -ksd '{"method":"Chain33.GetFatalFailure","params":[]}' ${MAIN_HTTP} | jq -r ".error")
[ "$r1" -eq 0 ] && [ "$error" == null ]
echo_rst "$FUNCNAME" "$?"
}
chain33_DecodeRawTransaction() {
tx="0a05636f696e73122c18010a281080c2d72f222131477444795771577233553637656a7663776d333867396e7a6e7a434b58434b7120a08d0630a696c0b3f78dd9ec083a2131477444795771577233553637656a7663776d333867396e7a6e7a434b58434b71"
r1=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'$tx'"}]}' ${MAIN_HTTP} | jq -r ".result.txs[0].execer")
[ "$r1" == "coins" ]
echo_rst "$FUNCNAME" "$?"
}
chain33_GetTimeStatus() {
r1=$(curl -ksd '{"method":"Chain33.GetTimeStatus","params":[]}' ${MAIN_HTTP} | jq -r ".result.localTime")
if [ -z "$r1" ]; then
curl -ksd '{"method":"Chain33.GetTimeStatus","params":[]}' ${MAIN_HTTP}
fi
[ -n "$r1" ]
echo_rst "$FUNCNAME" "$?"
}
chain33_GetLastBlockSequence() {
r1=$(curl -ksd '{"method":"Chain33.GetLastBlockSequence","params":[]}' ${MAIN_HTTP} | jq -r ".result")
[ "$r1" -ge 0 ]
echo_rst "$FUNCNAME" "$?"
}
chain33_GetBlockSequences() {
r1=$(curl -ksd '{"method":"Chain33.GetBlockSequences","params":[{"start":1,"end":3,"isDetail":true}]}' ${MAIN_HTTP} | jq ".result.blkseqInfos|length==3")
[ "$r1" == true ]
echo_rst "$FUNCNAME" "$?"
}
chain33_GetBlockByHashes() {
if [ "$IS_PARA" == true ]; then
geneis="0x97162f9d4a888121fdba2fb1ab402596acdbcb602121bd12284adb739d85f225"
statehash=$(curl -ksd '{"method":"Chain33.GetBlockByHashes","params":[{"hashes":["'"$geneis"'"]}]}' ${MAIN_HTTP} | jq -r ".result.items[0].block.stateHash")
[ "$statehash" == "0x2863c8dbc7fe3146c8d4e7acf2b8bbe4666264d658356e299e240f462a382a51" ]
echo_rst "$FUNCNAME" "$?"
else
hash0=$(curl -ksd '{"method":"Chain33.GetBlockSequences","params":[{"start":1,"end":3,"isDetail":true}]}' ${MAIN_HTTP} | jq -r ".result.blkseqInfos[0].hash")
hash1=$(curl -ksd '{"method":"Chain33.GetBlockSequences","params":[{"start":1,"end":3,"isDetail":true}]}' ${MAIN_HTTP} | jq -r ".result.blkseqInfos[1].hash")
hash2=$(curl -ksd '{"method":"Chain33.GetBlockSequences","params":[{"start":1,"end":3,"isDetail":true}]}' ${MAIN_HTTP} | jq -r ".result.blkseqInfos[2].hash")
# curl -ksd '{"method":"Chain33.GetBlockByHashes","params":[{"hashes":["'$hash1'","'$hash2'"]}]}' ${MAIN_HTTP}
# shellcheck disable=SC2086
p1=$(curl -ksd '{"method":"Chain33.GetBlockByHashes","params":[{"hashes":["'"$hash1"'","'"$hash2"'"]}]}' ${MAIN_HTTP} | jq -r ".result.items[0].block.parentHash")
# shellcheck disable=SC2086
p2=$(curl -ksd '{"method":"Chain33.GetBlockByHashes","params":[{"hashes":["'"$hash1"'","'"$hash2"'"]}]}' ${MAIN_HTTP} | jq -r ".result.items[1].block.parentHash")
[ "$p1" == "$hash0" ] && [ "$p2" == "$hash1" ]
echo_rst "$FUNCNAME" "$?"
fi
}
chain33_ConvertExectoAddr() {
r1=$(curl -ksd '{"method":"Chain33.ConvertExectoAddr","params":[{"execname":"coins"}]}' ${MAIN_HTTP} | jq -r ".result")
[ "$r1" == "1GaHYpWmqAJsqRwrpoNcB8VvgKtSwjcHqt" ]
echo_rst "$FUNCNAME" "$?"
}
chain33_GetExecBalance() {
local height=6802
statehash=$(curl -ksd '{"method":"Chain33.GetBlocks","params":[{"start":'$height',"end":'$height',"isDetail":false}]}' ${MAIN_HTTP} | jq -r ".result.items[0].block.stateHash")
state_base64=$(echo -n "$statehash" | cut -d " " -f 1 | xxd -r -p | base64)
addr="12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
addr_base64=$(echo -n "$addr" | base64)
# curl -ksd '{"method":"Chain33.GetExecBalance","params":[{"symbol":"bty","stateHash":"'$state_base64'","addr":"'$addr_base64'","execer":"coins","count":100}]}' ${MAIN_HTTP}
# shellcheck disable=SC2086
r1=$(curl -ksd '{"method":"Chain33.GetExecBalance","params":[{"symbol":"bty","stateHash":"'$state_base64'","addr":"'$addr_base64'","execer":"coins","count":100}]}' ${MAIN_HTTP} | jq -r ".error")
[ "$r1" == "null" ]
echo_rst "$FUNCNAME" "$?"
}
chain33_AddSeqCallBack() {
if [ "$IS_PARA" == true ]; then
echo_rst "$FUNCNAME" 2
else
r1=$(curl -ksd '{"method":"Chain33.AddSeqCallBack","params":[{"name":"test","url":"http://test","encode":"json"}]}' ${MAIN_HTTP} | jq -r ".result.isOK")
[ "$r1" == "true" ]
echo_rst "$FUNCNAME" "$?"
fi
}
chain33_ListSeqCallBack() {
if [ "$IS_PARA" == true ]; then
echo_rst "$FUNCNAME" 2
else
r1=$(curl -ksd '{"method":"Chain33.ListSeqCallBack","params":[]}' ${MAIN_HTTP} | jq -r ".result.items[0].name")
[ "$r1" == "test" ]
echo_rst "$FUNCNAME" "$?"
fi
}
chain33_GetSeqCallBackLastNum() {
r1=$(curl -ksd '{"method":"Chain33.GetSeqCallBackLastNum","params":[{"data":"test"}]}' ${MAIN_HTTP} | jq -r ".result.data")
[ "$r1" == "-1" ]
echo_rst "$FUNCNAME" "$?"
}
chain33_GetCoinSymbol() {
r1=$(curl -ksd '{"method":"Chain33.GetCoinSymbol","params":[]}' ${MAIN_HTTP} | jq -r ".result.data")
[ "$r1" == "bty" ]
echo_rst "$FUNCNAME" "$?"
}
chain33_GetHexTxByHash() {
#先获取一笔交易
reHash=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.GetTxByAddr","params":[{"addr":"14KEKbYtKKQm4wMthSK9J4La4nAiidGozt","flag":0,"count":1,"direction":0,"height":-1,"index":0}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r '.result.txInfos[0].hash')
#查询交易
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.GetHexTxByHash","params":[{"hash":"'"$reHash"'","upgrade":false}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result != null)' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
chain33_QueryTransaction() {
#先获取一笔交易
reHash=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.GetTxByAddr","params":[{"addr":"14KEKbYtKKQm4wMthSK9J4La4nAiidGozt","flag":0,"count":1,"direction":0,"height":-1,"index":0}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r '.result.txInfos[0].hash')
#查询交易
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.QueryTransaction","params":[{"hash":"'"$reHash"'","upgrade":false}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.receipt.tyName == "ExecOk") and (.result.height >= 0) and (.result.index >= 0) and (.result.amount >= 0)' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
chain33_GetBlocks() {
result=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.GetBlocks","params":[{"start":1,"end":2}]}' -H 'content-type:text/plain;' ${MAIN_HTTP} | jq -r ".result.items[1].block.height")
[ "$result" -eq 2 ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
chain33_GetLastHeader() {
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.GetLastHeader","params":[{}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.height >= 0) and (.result | [has("version","parentHash", "txHash", "stateHash", "height", "blockTime", "txCount", "hash", "difficulty"),true] | unique | length == 1)' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
chain33_GetTxByAddr() {
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.GetTxByAddr","params":[{"addr":"14KEKbYtKKQm4wMthSK9J4La4nAiidGozt","flag":0,"count":1,"direction":0,"height":-1,"index":0}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.txInfos[0].index >= 0) and (.result.txInfos[0] | [has("hash", "height", "index", "assets"),true] | unique | length == 1)' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
chain33_GetTxByHashes() {
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.GetTxByHashes","params":[{"hashes":["0x8040109d3859827d0f0c80ce91cc4ec80c496c45250f5e5755064b6da60842ab","0x501b910fd85d13d1ab7d776bce41a462f27c4bfeceb561dc47f0a11b10f452e4"]}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.txs|length == 2)' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
chain33_GetMempool() {
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.GetMempool","params":[{}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.txs|length >= 0)' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
chain33_GetAccountsV2() {
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.GetAccountsV2","params":[{}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.wallets|length >= 0)' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
chain33_GetAccounts() {
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.GetAccounts","params":[{}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.wallets|length >= 0)' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
chain33_NewAccount() {
resp=$(curl -ksd '{"jsonrpc":"2.0","id":2,"method":"Chain33.NewAccount","params":[{"label":"test169"}]}' -H 'content-type:text/plain;' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.label == "test169") and (.result.acc | [has("addr"),true] | unique | length == 1)' <<<"$resp")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
# hyb
chain33_CreateRawTransaction() {
local to="1EDDghAtgBsamrNEtNmYdQzC1QEhLkr87t"
local exec="coins"
local amount=10000000
tx=$(curl -ksd '{"method":"Chain33.CreateRawTransaction","params":[{"to":"'$to'","amount":'$amount'}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer == "'$exec'") and (.to == "'$to'")' <<<"$data")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
chain33_CreateTransaction() {
local to="1EDDghAtgBsamrNEtNmYdQzC1QEhLkr87t"
local exec="coins"
local amount=10000000
tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"coins","actionName":"Transfer","payload":{"to":"'$to'", "amount":'$amount'}}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP} | jq -r ".result.txs[0]")
ok=$(jq '(.execer == "'$exec'") and ((.payload.transfer.to) == "'$to'")' <<<"$data")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
chain33_ReWriteRawTx() {
local fee=1000000
local exec="coins"
local to="1EDDghAtgBsamrNEtNmYdQzC1QEhLkr87t"
local tx1="0a05636f696e73122d18010a291080ade20422223145444467684174674273616d724e45744e6d5964517a43315145684c6b7238377420a08d0630f6db93c0e0d3f1ff5e3a223145444467684174674273616d724e45744e6d5964517a43315145684c6b72383774"
tx=$(curl -ksd '{"method":"Chain33.ReWriteRawTx","params":[{"expire":"120s","fee":'$fee',"tx":"'$tx1'"}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.txs[0].execer == "'$exec'") and (.result.txs[0].to == "'$to'") and (.result.txs[0].fee == '$fee')' <<<"$data")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
chain33_CreateRawTxGroup() {
local to="1DNaSDRG9RD19s59meAoeN4a2F6RH97fSo"
local exec="user.write"
local groupCount=2
fee=1000000
tx1="0a0a757365722e7772697465121d236d642368616b6468676f7177656a6872676f716a676f6a71776c6a6720a08d0630a0b7b1b1dda2f4c5743a2231444e615344524739524431397335396d65416f654e34613246365248393766536f"
tx2="0a0a757365722e7772697465121d236d642368616b6468676f7177656a6872676f716a676f6a71776c6a6720a08d0630c5838f94e2f49acb4b3a2231444e615344524739524431397335396d65416f654e34613246365248393766536f"
tx=$(curl -ksd '{"method":"Chain33.CreateRawTxGroup","params":[{"txs":["'$tx1'","'$tx2'"]}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.txs[0].execer == "'$exec'") and (.result.txs[0].to == "'$to'") and (.result.txs[0].groupCount == '$groupCount') and (.result.txs[1].execer == "'$exec'") and (.result.txs[1].to == "'$to'") and (.result.txs[1].groupCount == '$groupCount')' <<<"$data")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
chain33_SignRawTx() {
local fee=1000000
local exec="coins"
local to="1EDDghAtgBsamrNEtNmYdQzC1QEhLkr87t"
local from="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
local privkey="CC38546E9E659D15E6B4893F0AB32A06D103931A8230B0BDE71459D2B27D6944"
tx1="0a05636f696e73122d18010a291080ade20422223145444467684174674273616d724e45744e6d5964517a43315145684c6b7238377420a08d0628e1ddcae60530f6db93c0e0d3f1ff5e3a223145444467684174674273616d724e45744e6d5964517a43315145684c6b72383774"
tx=$(curl -ksd '{"method":"Chain33.SignRawTx","params":[{"expire":"120s","fee":'$fee',"privkey":"'$privkey'","txHex":"'$tx1'"}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.txs[0].execer == "'$exec'") and (.result.txs[0].to == "'$to'") and (.result.txs[0].fee == '$fee') and (.result.txs[0].from == "'$from'")' <<<"$data")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
chain33_SendTransaction() {
local fee=1000000
local exec="coins"
local to="1EDDghAtgBsamrNEtNmYdQzC1QEhLkr87t"
local from="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
local privkey="CC38546E9E659D15E6B4893F0AB32A06D103931A8230B0BDE71459D2B27D6944"
tx1="0a05636f696e73122d18010a291080ade20422223145444467684174674273616d724e45744e6d5964517a43315145684c6b7238377420a08d0628e1ddcae60530f6db93c0e0d3f1ff5e3a223145444467684174674273616d724e45744e6d5964517a43315145684c6b72383774"
tx=$(curl -ksd '{"method":"Chain33.SignRawTx","params":[{"expire":"120s","fee":'$fee',"privkey":"'$privkey'","txHex":"'$tx1'"}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.SendTransaction","params":[{"data":"'"$tx"'"}]}' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result != null)' <<<"$data")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
chain33_CreateNoBalanceTransaction() {
local to="1EDDghAtgBsamrNEtNmYdQzC1QEhLkr87t"
local txHex="0a05636f696e73122d18010a291080ade20422223145444467684174674273616d724e45744e6d5964517a43315145684c6b7238377420a08d0630a1938af2e88e97fb0d3a223145444467684174674273616d724e45744e6d5964517a43315145684c6b72383774"
tx=$(curl -ksd '{"method":"Chain33.CreateNoBalanceTransaction","params":[{"txHex":"'$txHex'"}]}' ${MAIN_HTTP} | jq -r ".result")
data=$(curl -ksd '{"method":"Chain33.DecodeRawTransaction","params":[{"txHex":"'"$tx"'"}]}' ${MAIN_HTTP})
ok=$(jq '(.error|not) and (.result.txs[0].execer == "none") and (.result.txs[0].groupCount == 2) and (.result.txs[1].execer == "coins") and (.result.txs[1].groupCount == 2) and (.result.txs[1].to == "'$to'")' <<<"$data")
[ "$ok" == true ]
rst=$?
echo_rst "$FUNCNAME" "$rst"
}
chain33_GetBlockHash() {
req='{"method":"Chain33.GetBlockHash", "params":[{"height":1}]}'
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#response: $resp"
ok=$(jq '(.error|not) and (.result| has("hash"))' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
}
chain33_GenSeed() {
req='{"method":"Chain33.GenSeed", "params":[{"lang":0}]}'
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#response: $resp"
ok=$(jq '(.error|not) and (.result| has("seed"))' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
seed=$(jq '(.result.seed)' <<<"$resp")
}
chain33_SaveSeed() {
req='{"method":"Chain33.SaveSeed", "params":[{"seed":'"$seed"', "passwd": "1314fuzamei"}]}'
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#response: $resp"
ok=$(jq '(.error|not) and (.result| has("isOK"))' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
}
chain33_GetSeed() {
req='{"method":"Chain33.GetSeed", "params":[{"passwd": "1314fuzamei"}]}'
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#response: $resp"
ok=$(jq '(.error|not) and (.result| has("seed"))' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
}
chain33_testSeed() {
seed=""
chain33_GenSeed
chain33_SaveSeed
chain33_GetSeed
}
chain33_GetWalletStatus() {
req='{"method":"Chain33.GetWalletStatus", "params":[{}]}'
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#response: $resp"
ok=$(jq '(.error|not) and (.result| [has("isWalletLock", "isAutoMining", "isHasSeed", "isTicketLock"), true] | unique | length == 1)' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
}
chain33_GetBalance() {
req='{"method":"Chain33.GetBalance", "params":[{"addresses" : ["14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"], "execer" : "coins"}]}'
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#response: $resp"
ok=$(jq '(.error|not) and (.result[0] | [has("balance", "frozen"), true] | unique | length == 1)' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
}
chain33_GetAllExecBalance() {
req='{"method":"Chain33.GetAllExecBalance", "params":[{"addr" : "14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"}]}'
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#response: $resp"
ok=$(jq '(.error|not) and (.result| [has("addr", "execAccount"), true] | unique | length == 1)' <<<"$resp")
[ "$ok" == true ]
ok=$(jq '(.result.execAccount | [map(has("execer", "account")), true] | flatten | unique | length == 1)' <<<"$resp")
[ "$ok" == true ]
ok=$(jq '(.result.execAccount[].account | [.] | [map(has("balance", "frozen")), true] | flatten | unique | length == 1)' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
}
chain33_ExecWallet() {
req='{"method":"Chain33.ExecWallet", "params":[{"funcName" : "NewAccountByIndex", "payload" : {"data" : 100000009}, "stateHash" : "", "execer" : "wallet" }]}'
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#response: $resp"
ok=$(jq '(.error|not) and (.result | has("data"))' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
}
chain33_Query() {
req='{"method":"Chain33.Query", "params":[{ "execer":"coins", "funcName": "GetTxsByAddr", "payload" : {"addr" : "1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4"}}]}'
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#response: $resp"
ok=$(jq '(. | has("result"))' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
}
chain33_Version() {
req='{"method":"Chain33.Version", "params":[{}]}'
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#response: $resp"
ok=$(jq '(.error|not) and (.result)' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
}
chain33_GetTotalCoins() {
req='{"method":"Chain33.GetTotalCoins", "params":[{"symbol" : "bty", "stateHash":"", "startKey":"", "count":2, "execer":"coins"}]}'
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#response: $resp"
ok=$(jq '(.error|not) and (.result| has("count"))' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
}
chain33_IsSync() {
req='{"method":"Chain33.IsSync", "params":[{}]}'
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#response: $resp"
ok=$(jq '(.error|not) and (. | has("result"))' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
}
chain33_IsNtpClockSync() {
req='{"method":"Chain33.IsNtpClockSync", "params":[{}]}'
resp=$(curl -ksd "$req" "${MAIN_HTTP}")
# echo "#response: $resp"
ok=$(jq '(.error|not) and (. | has("result"))' <<<"$resp")
[ "$ok" == true ]
echo_rst "$FUNCNAME" "$?"
}
run_testcases() {
# set -x # set -x
set +e set +e
IS_PARA=$(echo '"'"${1}"'"' | jq '.|contains("8901")')
echo "ipara=$IS_PARA"
chain33_lock chain33_lock
chain33_unlock chain33_unlock
chain33_WalletTxList "$ip" chain33_WalletTxList "$1"
chain33_ImportPrivkey "$ip" chain33_ImportPrivkey "$1"
chain33_DumpPrivkey "$ip" chain33_DumpPrivkey "$1"
chain33_SendToAddress "$ip" chain33_SendToAddress "$1"
chain33_SetTxFee "$ip" chain33_SetTxFee "$1"
chain33_SetLabl "$ip" chain33_SetLabl "$1"
chain33_GetPeerInfo "$ip" chain33_GetPeerInfo "$1"
chain33_GetHeaders "$ip" chain33_GetHeaders "$1"
chain33_GetLastMemPool "$ip" chain33_GetLastMemPool "$1"
chain33_GetProperFee "$ip" chain33_GetProperFee "$1"
chain33_GetBlockOverview "$ip" chain33_GetBlockOverview "$1"
chain33_GetAddrOverview "$ip" chain33_GetAddrOverview "$1"
chain33_QueryTotalFee
chain33_GetNetInfo
chain33_GetFatalFailure
chain33_DecodeRawTransaction
chain33_GetTimeStatus
chain33_GetLastBlockSequence
chain33_GetBlockSequences
chain33_GetBlockByHashes
chain33_ConvertExectoAddr
chain33_GetExecBalance
chain33_AddSeqCallBack
chain33_ListSeqCallBack
chain33_GetSeqCallBackLastNum
chain33_GetCoinSymbol
chain33_GetHexTxByHash
chain33_QueryTransaction
chain33_GetBlocks
chain33_GetLastHeader
chain33_GetTxByAddr
chain33_GetTxByHashes
chain33_GetMempool
chain33_GetAccountsV2
chain33_GetAccounts
chain33_NewAccount
chain33_CreateRawTransaction
chain33_CreateTransaction
chain33_ReWriteRawTx
chain33_CreateRawTxGroup
chain33_SignRawTx
chain33_SendTransaction
chain33_CreateNoBalanceTransaction
chain33_GetBlockHash
chain33_testSeed
chain33_GetWalletStatus
chain33_GetBalance
chain33_GetAllExecBalance
chain33_ExecWallet
chain33_Query
chain33_Version
chain33_GetTotalCoins
chain33_IsSync
chain33_IsNtpClockSync
#这两个测试放在最后 #这两个测试放在最后
chain33_SetPasswd "$ip" chain33_SetPasswd "$1"
chain33_MergeBalance "$ip" chain33_MergeBalance "$1"
set -e set -e
}
function system_test_rpc() {
MAIN_HTTP=$1
echo "=========== # system rpc test ============="
echo "ip=$1"
run_testcases "$1"
if [ -n "$CASE_ERR" ]; then if [ -n "$CASE_ERR" ]; then
echo -e "${RED}======system rpc test fail=======${NOC}" echo -e "${RED}======system rpc test fail=======${NOC}"
exit 1 exit 1
...@@ -233,4 +759,4 @@ function system_test_rpc() { ...@@ -233,4 +759,4 @@ function system_test_rpc() {
fi fi
} }
#system_rpc_test #system_test_rpc $1
...@@ -1229,29 +1229,6 @@ func (_m *QueueProtocolAPI) Version() (*types.VersionInfo, error) { ...@@ -1229,29 +1229,6 @@ func (_m *QueueProtocolAPI) Version() (*types.VersionInfo, error) {
return r0, r1 return r0, r1
} }
// WalletCreateTx provides a mock function with given fields: param
func (_m *QueueProtocolAPI) WalletCreateTx(param *types.ReqCreateTransaction) (*types.Transaction, error) {
ret := _m.Called(param)
var r0 *types.Transaction
if rf, ok := ret.Get(0).(func(*types.ReqCreateTransaction) *types.Transaction); ok {
r0 = rf(param)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.Transaction)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(*types.ReqCreateTransaction) error); ok {
r1 = rf(param)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// WalletGetAccountList provides a mock function with given fields: req // WalletGetAccountList provides a mock function with given fields: req
func (_m *QueueProtocolAPI) WalletGetAccountList(req *types.ReqAccountList) (*types.WalletAccounts, error) { func (_m *QueueProtocolAPI) WalletGetAccountList(req *types.ReqAccountList) (*types.WalletAccounts, error) {
ret := _m.Called(req) ret := _m.Called(req)
......
...@@ -1007,19 +1007,6 @@ func (q *QueueProtocol) GetSequenceByHash(param *types.ReqHash) (*types.Int64, e ...@@ -1007,19 +1007,6 @@ func (q *QueueProtocol) GetSequenceByHash(param *types.ReqHash) (*types.Int64, e
return nil, types.ErrTypeAsset return nil, types.ErrTypeAsset
} }
// WalletCreateTx create transaction
func (q *QueueProtocol) WalletCreateTx(param *types.ReqCreateTransaction) (*types.Transaction, error) {
msg, err := q.query(walletKey, types.EventWalletCreateTx, param)
if err != nil {
log.Error("CreateTrasaction", "Error", err.Error())
return nil, err
}
if reply, ok := msg.GetData().(*types.Transaction); ok {
return reply, nil
}
return nil, types.ErrTypeAsset
}
// GetBlockByHashes get block detail list by hash list // GetBlockByHashes get block detail list by hash list
func (q *QueueProtocol) GetBlockByHashes(param *types.ReqHashes) (*types.BlockDetails, error) { func (q *QueueProtocol) GetBlockByHashes(param *types.ReqHashes) (*types.BlockDetails, error) {
if param == nil { if param == nil {
......
...@@ -94,8 +94,6 @@ type QueueProtocolAPI interface { ...@@ -94,8 +94,6 @@ type QueueProtocolAPI interface {
// types.EventSignRawTx // types.EventSignRawTx
SignRawTx(param *types.ReqSignRawTx) (*types.ReplySignRawTx, error) SignRawTx(param *types.ReqSignRawTx) (*types.ReplySignRawTx, error)
GetFatalFailure() (*types.Int32, error) GetFatalFailure() (*types.Int32, error)
// types.EventCreateTransaction 由服务器协助创建一个交易
WalletCreateTx(param *types.ReqCreateTransaction) (*types.Transaction, error)
// types.EventGetBlocks // types.EventGetBlocks
GetBlocks(param *types.ReqBlocks) (*types.BlockDetails, error) GetBlocks(param *types.ReqBlocks) (*types.BlockDetails, error)
// types.EventQueryTx // types.EventQueryTx
......
// 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 p256
import (
"crypto/ecdsa"
"crypto/elliptic"
"errors"
"math/big"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/vrf"
)
// GenVrfKey returns vrf private and public key
func GenVrfKey(key crypto.PrivKey) (vrf.PrivateKey, vrf.PublicKey, []byte) {
priv, pub := PrivKeyFromBytes(elliptic.P256(), key.Bytes())
return &PrivateKey{PrivateKey: priv}, &PublicKey{PublicKey: pub}, SerializePublicKey(pub)
}
// PrivKeyFromBytes return ecdsa private and public key
func PrivKeyFromBytes(curve elliptic.Curve, pk []byte) (*ecdsa.PrivateKey, *ecdsa.PublicKey) {
x, y := curve.ScalarBaseMult(pk)
priv := &ecdsa.PrivateKey{
PublicKey: ecdsa.PublicKey{
Curve: curve,
X: x,
Y: y,
},
D: new(big.Int).SetBytes(pk),
}
return priv, &priv.PublicKey
}
// SerializePublicKey serialize public key
func SerializePublicKey(p *ecdsa.PublicKey) []byte {
b := make([]byte, 0, 65)
b = append(b, 0x4)
b = paddedAppend(32, b, p.X.Bytes())
return paddedAppend(32, b, p.Y.Bytes())
}
func paddedAppend(size uint, dst, src []byte) []byte {
for i := 0; i < int(size)-len(src); i++ {
dst = append(dst, 0)
}
return append(dst, src...)
}
// ParseVrfPubKey parse public key
func ParseVrfPubKey(pubKeyStr []byte) (vrf.PublicKey, error) {
pubkey := &ecdsa.PublicKey{}
pubkey.Curve = elliptic.P256()
if len(pubKeyStr) == 0 {
return nil, errors.New("pubkey string is empty")
}
pubkey.X = new(big.Int).SetBytes(pubKeyStr[1:33])
pubkey.Y = new(big.Int).SetBytes(pubKeyStr[33:])
if pubkey.X.Cmp(pubkey.Curve.Params().P) >= 0 {
return nil, errors.New("pubkey X parameter is >= to P")
}
if pubkey.Y.Cmp(pubkey.Curve.Params().P) >= 0 {
return nil, errors.New("pubkey Y parameter is >= to P")
}
if !pubkey.Curve.IsOnCurve(pubkey.X, pubkey.Y) {
return nil, errors.New("pubkey isn't on secp256k1 curve")
}
return &PublicKey{PublicKey: pubkey}, 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 p256
import (
"testing"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/vrf"
"github.com/33cn/chain33/types"
"github.com/stretchr/testify/assert"
)
func Test_GenerateKey(t *testing.T) {
k, pk := GenerateKey()
testVRF(t, k, pk)
}
func Test_GenVrfKey(t *testing.T) {
c, err := crypto.New(types.GetSignName("", types.SECP256K1))
assert.NoError(t, err)
priv, err := c.GenKey()
assert.NoError(t, err)
vpriv, _, pubKey := GenVrfKey(priv)
vpub, err := ParseVrfPubKey(pubKey)
assert.NoError(t, err)
testVRF(t, vpriv, vpub)
}
func testVRF(t *testing.T, priv vrf.PrivateKey, pub vrf.PublicKey) {
m1 := []byte("data1")
m2 := []byte("data2")
m3 := []byte("data2")
hash1, proof1 := priv.Evaluate(m1)
hash2, proof2 := priv.Evaluate(m2)
hash3, proof3 := priv.Evaluate(m3)
for _, tc := range []struct {
m []byte
hash [32]byte
proof []byte
err error
}{
{m1, hash1, proof1, nil},
{m2, hash2, proof2, nil},
{m3, hash3, proof3, nil},
{m3, hash3, proof2, nil},
{m3, hash3, proof1, ErrInvalidVRF},
} {
hash, err := pub.ProofToHash(tc.m, tc.proof)
if got, want := err, tc.err; got != want {
t.Errorf("ProofToHash(%s, %x): %v, want %v", tc.m, tc.proof, got, want)
}
if err != nil {
continue
}
if got, want := hash, tc.hash; got != want {
t.Errorf("ProofToHash(%s, %x): %x, want %x", tc.m, tc.proof, got, want)
}
}
}
...@@ -2,8 +2,22 @@ ...@@ -2,8 +2,22 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Package p256 implements a verifiable random function using curve p256. // Copyright 2016 Google Inc. All Rights Reserved.
package p256 //
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package secp256k1 implements a verifiable random function using curve secp256k1.
package secp256k1
import ( import (
"bytes" "bytes"
...@@ -19,11 +33,11 @@ import ( ...@@ -19,11 +33,11 @@ import (
"math/big" "math/big"
vrfp "github.com/33cn/chain33/common/vrf" vrfp "github.com/33cn/chain33/common/vrf"
"github.com/btcsuite/btcd/btcec"
) )
var ( var (
curve = elliptic.P256() curve = btcec.S256()
params = curve.Params()
// ErrInvalidVRF err // ErrInvalidVRF err
ErrInvalidVRF = errors.New("invalid VRF proof") ErrInvalidVRF = errors.New("invalid VRF proof")
) )
...@@ -52,7 +66,7 @@ func GenerateKey() (vrfp.PrivateKey, vrfp.PublicKey) { ...@@ -52,7 +66,7 @@ func GenerateKey() (vrfp.PrivateKey, vrfp.PublicKey) {
func H1(m []byte) (x, y *big.Int) { func H1(m []byte) (x, y *big.Int) {
h := sha512.New() h := sha512.New()
var i uint32 var i uint32
byteLen := (params.BitSize + 7) >> 3 byteLen := (curve.BitSize + 7) >> 3
for x == nil && i < 100 { for x == nil && i < 100 {
// TODO: Use a NIST specified DRBG. // TODO: Use a NIST specified DRBG.
h.Reset() h.Reset()
...@@ -75,7 +89,7 @@ var one = big.NewInt(1) ...@@ -75,7 +89,7 @@ var one = big.NewInt(1)
// H2 hashes to an integer [1,N-1] // H2 hashes to an integer [1,N-1]
func H2(m []byte) *big.Int { func H2(m []byte) *big.Int {
// NIST SP 800-90A § A.5.1: Simple discard method. // NIST SP 800-90A § A.5.1: Simple discard method.
byteLen := (params.BitSize + 7) >> 3 byteLen := (curve.BitSize + 7) >> 3
h := sha512.New() h := sha512.New()
for i := uint32(0); ; i++ { for i := uint32(0); ; i++ {
// TODO: Use a NIST specified DRBG. // TODO: Use a NIST specified DRBG.
...@@ -88,7 +102,7 @@ func H2(m []byte) *big.Int { ...@@ -88,7 +102,7 @@ func H2(m []byte) *big.Int {
} }
b := h.Sum(nil) b := h.Sum(nil)
k := new(big.Int).SetBytes(b[:byteLen]) k := new(big.Int).SetBytes(b[:byteLen])
if k.Cmp(new(big.Int).Sub(params.N, one)) == -1 { if k.Cmp(new(big.Int).Sub(curve.N, one)) == -1 {
return k.Add(k, one) return k.Add(k, one)
} }
} }
...@@ -108,15 +122,15 @@ func (k PrivateKey) Evaluate(m []byte) (index [32]byte, proof []byte) { ...@@ -108,15 +122,15 @@ func (k PrivateKey) Evaluate(m []byte) (index [32]byte, proof []byte) {
Hx, Hy := H1(m) Hx, Hy := H1(m)
// VRF_k(m) = [k]H // VRF_k(m) = [k]H
sHx, sHy := params.ScalarMult(Hx, Hy, k.D.Bytes()) sHx, sHy := curve.ScalarMult(Hx, Hy, k.D.Bytes())
vrf := elliptic.Marshal(curve, sHx, sHy) // 65 bytes. vrf := elliptic.Marshal(curve, sHx, sHy) // 65 bytes.
// G is the base point // G is the base point
// s = H2(G, H, [k]G, VRF, [r]G, [r]H) // s = H2(G, H, [k]G, VRF, [r]G, [r]H)
rGx, rGy := params.ScalarBaseMult(r) rGx, rGy := curve.ScalarBaseMult(r)
rHx, rHy := params.ScalarMult(Hx, Hy, r) rHx, rHy := curve.ScalarMult(Hx, Hy, r)
var b bytes.Buffer var b bytes.Buffer
if _, err := b.Write(elliptic.Marshal(curve, params.Gx, params.Gy)); err != nil { if _, err := b.Write(elliptic.Marshal(curve, curve.Gx, curve.Gy)); err != nil {
panic(err) panic(err)
} }
if _, err := b.Write(elliptic.Marshal(curve, Hx, Hy)); err != nil { if _, err := b.Write(elliptic.Marshal(curve, Hx, Hy)); err != nil {
...@@ -138,7 +152,7 @@ func (k PrivateKey) Evaluate(m []byte) (index [32]byte, proof []byte) { ...@@ -138,7 +152,7 @@ func (k PrivateKey) Evaluate(m []byte) (index [32]byte, proof []byte) {
// t = r−s*k mod N // t = r−s*k mod N
t := new(big.Int).Sub(ri, new(big.Int).Mul(s, k.D)) t := new(big.Int).Sub(ri, new(big.Int).Mul(s, k.D))
t.Mod(t, params.N) t.Mod(t, curve.N)
// Index = H(vrf) // Index = H(vrf)
index = sha256.Sum256(vrf) index = sha256.Sum256(vrf)
...@@ -184,22 +198,22 @@ func (pk *PublicKey) ProofToHash(m, proof []byte) (index [32]byte, err error) { ...@@ -184,22 +198,22 @@ func (pk *PublicKey) ProofToHash(m, proof []byte) (index [32]byte, err error) {
} }
// [t]G + [s]([k]G) = [t+ks]G // [t]G + [s]([k]G) = [t+ks]G
tGx, tGy := params.ScalarBaseMult(t) tGx, tGy := curve.ScalarBaseMult(t)
ksGx, ksGy := params.ScalarMult(pk.X, pk.Y, s) ksGx, ksGy := curve.ScalarMult(pk.X, pk.Y, s)
tksGx, tksGy := params.Add(tGx, tGy, ksGx, ksGy) tksGx, tksGy := curve.Add(tGx, tGy, ksGx, ksGy)
// H = H1(m) // H = H1(m)
// [t]H + [s]VRF = [t+ks]H // [t]H + [s]VRF = [t+ks]H
Hx, Hy := H1(m) Hx, Hy := H1(m)
tHx, tHy := params.ScalarMult(Hx, Hy, t) tHx, tHy := curve.ScalarMult(Hx, Hy, t)
sHx, sHy := params.ScalarMult(uHx, uHy, s) sHx, sHy := curve.ScalarMult(uHx, uHy, s)
tksHx, tksHy := params.Add(tHx, tHy, sHx, sHy) tksHx, tksHy := curve.Add(tHx, tHy, sHx, sHy)
// H2(G, H, [k]G, VRF, [t]G + [s]([k]G), [t]H + [s]VRF) // H2(G, H, [k]G, VRF, [t]G + [s]([k]G), [t]H + [s]VRF)
// = H2(G, H, [k]G, VRF, [t+ks]G, [t+ks]H) // = H2(G, H, [k]G, VRF, [t+ks]G, [t+ks]H)
// = H2(G, H, [k]G, VRF, [r]G, [r]H) // = H2(G, H, [k]G, VRF, [r]G, [r]H)
var b bytes.Buffer var b bytes.Buffer
if _, err := b.Write(elliptic.Marshal(curve, params.Gx, params.Gy)); err != nil { if _, err := b.Write(elliptic.Marshal(curve, curve.Gx, curve.Gy)); err != nil {
panic(err) panic(err)
} }
if _, err := b.Write(elliptic.Marshal(curve, Hx, Hy)); err != nil { if _, err := b.Write(elliptic.Marshal(curve, Hx, Hy)); err != nil {
......
...@@ -2,7 +2,21 @@ ...@@ -2,7 +2,21 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package p256 // Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package secp256k1
import ( import (
"bytes" "bytes"
...@@ -21,7 +35,7 @@ func TestH1(t *testing.T) { ...@@ -21,7 +35,7 @@ func TestH1(t *testing.T) {
if x == nil { if x == nil {
t.Errorf("H1(%v)=%v, want curve point", m, x) t.Errorf("H1(%v)=%v, want curve point", m, x)
} }
if got := curve.Params().IsOnCurve(x, y); !got { if got := curve.IsOnCurve(x, y); !got {
t.Errorf("H1(%v)=[%v, %v], is not on curve", m, x, y) t.Errorf("H1(%v)=[%v, %v], is not on curve", m, x, y)
} }
} }
......
...@@ -2,7 +2,21 @@ ...@@ -2,7 +2,21 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package p256 // Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package secp256k1
import ( import (
"crypto/elliptic" "crypto/elliptic"
...@@ -42,17 +56,17 @@ func Unmarshal(curve elliptic.Curve, data []byte) (x, y *big.Int) { ...@@ -42,17 +56,17 @@ func Unmarshal(curve elliptic.Curve, data []byte) (x, y *big.Int) {
} }
// Use the curve equation to calculate y² given x. // Use the curve equation to calculate y² given x.
// only applies to curves of the form y² = x³ - 3x + b. // only applies to curves of the form y² = x³ + b.
func y2(curve *elliptic.CurveParams, x *big.Int) *big.Int { func y2(curve *elliptic.CurveParams, x *big.Int) *big.Int {
// y² = x³ - 3x + b // y² = x³ + b
x3 := new(big.Int).Mul(x, x) x3 := new(big.Int).Mul(x, x)
x3.Mul(x3, x) x3.Mul(x3, x)
threeX := new(big.Int).Lsh(x, 1) //threeX := new(big.Int).Lsh(x, 1)
threeX.Add(threeX, x) //threeX.Add(threeX, x)
//
x3.Sub(x3, threeX) //x3.Sub(x3, threeX)
x3.Add(x3, curve.B) x3.Add(x3, curve.B)
x3.Mod(x3, curve.P) x3.Mod(x3, curve.P)
return x3 return x3
......
...@@ -2,6 +2,20 @@ ...@@ -2,6 +2,20 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package vrf defines the interface to a verifiable random function. // Package vrf defines the interface to a verifiable random function.
package vrf package vrf
......
...@@ -728,7 +728,13 @@ func (c *Chain33) GetWalletStatus(in types.ReqNil, result *interface{}) error { ...@@ -728,7 +728,13 @@ func (c *Chain33) GetWalletStatus(in types.ReqNil, result *interface{}) error {
if err != nil { if err != nil {
return err return err
} }
*result = reply status := rpctypes.WalletStatus{
IsWalletLock: reply.IsWalletLock,
IsAutoMining: reply.IsAutoMining,
IsHasSeed: reply.IsHasSeed,
IsTicketLock: reply.IsTicketLock,
}
*result = &status
return nil return nil
} }
...@@ -982,17 +988,6 @@ func (c *Chain33) GetTimeStatus(in *types.ReqNil, result *interface{}) error { ...@@ -982,17 +988,6 @@ func (c *Chain33) GetTimeStatus(in *types.ReqNil, result *interface{}) error {
return nil return nil
} }
// WalletCreateTx wallet create tx
func (c *Chain33) WalletCreateTx(in types.ReqCreateTransaction, result *interface{}) error {
reply, err := c.cli.WalletCreateTx(&in)
if err != nil {
return err
}
txHex := types.Encode(reply)
*result = hex.EncodeToString(txHex)
return nil
}
// CloseQueue close queue // CloseQueue close queue
func (c *Chain33) CloseQueue(in *types.ReqNil, result *interface{}) error { func (c *Chain33) CloseQueue(in *types.ReqNil, result *interface{}) error {
go func() { go func() {
......
...@@ -1073,8 +1073,7 @@ func TestChain33_GetWalletStatus(t *testing.T) { ...@@ -1073,8 +1073,7 @@ func TestChain33_GetWalletStatus(t *testing.T) {
api := new(mocks.QueueProtocolAPI) api := new(mocks.QueueProtocolAPI)
testChain33 := newTestChain33(api) testChain33 := newTestChain33(api)
// expected := &types.GetSeedByPw{} api.On("GetWalletStatus").Return(nil, errors.New("error value")).Once()
api.On("GetWalletStatus").Return(nil, errors.New("error value"))
var testResult interface{} var testResult interface{}
actual := types.ReqNil{} actual := types.ReqNil{}
...@@ -1083,6 +1082,25 @@ func TestChain33_GetWalletStatus(t *testing.T) { ...@@ -1083,6 +1082,25 @@ func TestChain33_GetWalletStatus(t *testing.T) {
assert.Equal(t, nil, testResult) assert.Equal(t, nil, testResult)
assert.NotNil(t, err) assert.NotNil(t, err)
expect := types.WalletStatus{
IsWalletLock: true,
IsAutoMining: true,
IsHasSeed: false,
IsTicketLock: false,
}
api.On("GetWalletStatus").Return(&expect, nil).Once()
err = testChain33.GetWalletStatus(actual, &testResult)
t.Log(err)
assert.Nil(t, err)
status, ok := testResult.(*rpctypes.WalletStatus)
if !ok {
t.Error("GetWalletStatus type error")
}
assert.Equal(t, expect.IsWalletLock, status.IsWalletLock)
assert.Equal(t, expect.IsAutoMining, status.IsAutoMining)
assert.Equal(t, expect.IsHasSeed, status.IsHasSeed)
assert.Equal(t, expect.IsTicketLock, status.IsTicketLock)
mock.AssertExpectationsForObjects(t, api) mock.AssertExpectationsForObjects(t, api)
} }
...@@ -1343,15 +1361,6 @@ func TestChain33_DecodeRawTransaction(t *testing.T) { ...@@ -1343,15 +1361,6 @@ func TestChain33_DecodeRawTransaction(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
} }
func TestChain33_WalletCreateTx(t *testing.T) {
api := new(mocks.QueueProtocolAPI)
client := newTestChain33(api)
var testResult interface{}
api.On("WalletCreateTx", mock.Anything).Return(&types.Transaction{}, nil)
err := client.WalletCreateTx(types.ReqCreateTransaction{}, &testResult)
assert.NoError(t, err)
}
func TestChain33_CloseQueue(t *testing.T) { func TestChain33_CloseQueue(t *testing.T) {
api := new(mocks.QueueProtocolAPI) api := new(mocks.QueueProtocolAPI)
client := newTestChain33(api) client := newTestChain33(api)
......
...@@ -791,18 +791,34 @@ func TestAddTxGroup(t *testing.T) { ...@@ -791,18 +791,34 @@ func TestAddTxGroup(t *testing.T) {
q, mem := initEnv(0) q, mem := initEnv(0)
defer q.Close() defer q.Close()
defer mem.Close() defer mem.Close()
toAddr := "1PjMi9yGTjA9bbqUZa1Sj7dAUKyLA8KqE1"
//copytx //copytx
ctx2 := *tx2 crouptx1 := types.Transaction{Execer: []byte("coins"), Payload: types.Encode(transfer), Fee: 460000000, Expire: 0, To: toAddr}
ctx3 := *tx3 crouptx2 := types.Transaction{Execer: []byte("coins"), Payload: types.Encode(transfer), Fee: 100, Expire: 0, To: toAddr}
ctx4 := *tx4 crouptx3 := types.Transaction{Execer: []byte("coins"), Payload: types.Encode(transfer), Fee: 100000000, Expire: 0, To: toAddr}
txGroup, _ := types.CreateTxGroup([]*types.Transaction{&ctx2, &ctx3, &ctx4}) crouptx4 := types.Transaction{Execer: []byte("user.write"), Payload: types.Encode(transfer), Fee: 100000000, Expire: 0, To: toAddr}
txGroup, _ := types.CreateTxGroup([]*types.Transaction{&crouptx1, &crouptx2, &crouptx3, &crouptx4})
for i := range txGroup.Txs {
err := txGroup.SignN(i, types.SECP256K1, mainPriv)
if err != nil {
t.Error("TestAddTxGroup SignNfailed ", err.Error())
}
}
tx := txGroup.Tx() tx := txGroup.Tx()
msg := mem.client.NewMessage("mempool", types.EventTx, tx) msg := mem.client.NewMessage("mempool", types.EventTx, tx)
mem.client.Send(msg, true) mem.client.Send(msg, true)
_, err := mem.client.Wait(msg) resp, err := mem.client.Wait(msg)
if err != nil { if err != nil {
t.Error("TestAddTxGroup failed", err.Error()) t.Error("TestAddTxGroup failed", err.Error())
} }
reply := resp.GetData().(*types.Reply)
if !reply.GetIsOk() {
t.Error("TestAddTxGroup failed", string(reply.GetMsg()))
}
} }
func BenchmarkMempool(b *testing.B) { func BenchmarkMempool(b *testing.B) {
......
...@@ -451,6 +451,45 @@ func (m *BlockSeq) GetDetail() *BlockDetail { ...@@ -451,6 +451,45 @@ func (m *BlockSeq) GetDetail() *BlockDetail {
return nil return nil
} }
type BlockSeqs struct {
Seqs []*BlockSeq `protobuf:"bytes,1,rep,name=seqs,proto3" json:"seqs,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *BlockSeqs) Reset() { *m = BlockSeqs{} }
func (m *BlockSeqs) String() string { return proto.CompactTextString(m) }
func (*BlockSeqs) ProtoMessage() {}
func (*BlockSeqs) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{6}
}
func (m *BlockSeqs) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BlockSeqs.Unmarshal(m, b)
}
func (m *BlockSeqs) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_BlockSeqs.Marshal(b, m, deterministic)
}
func (m *BlockSeqs) XXX_Merge(src proto.Message) {
xxx_messageInfo_BlockSeqs.Merge(m, src)
}
func (m *BlockSeqs) XXX_Size() int {
return xxx_messageInfo_BlockSeqs.Size(m)
}
func (m *BlockSeqs) XXX_DiscardUnknown() {
xxx_messageInfo_BlockSeqs.DiscardUnknown(m)
}
var xxx_messageInfo_BlockSeqs proto.InternalMessageInfo
func (m *BlockSeqs) GetSeqs() []*BlockSeq {
if m != nil {
return m.Seqs
}
return nil
}
//节点ID以及对应的Block //节点ID以及对应的Block
type BlockPid struct { type BlockPid struct {
Pid string `protobuf:"bytes,1,opt,name=pid,proto3" json:"pid,omitempty"` Pid string `protobuf:"bytes,1,opt,name=pid,proto3" json:"pid,omitempty"`
...@@ -464,7 +503,7 @@ func (m *BlockPid) Reset() { *m = BlockPid{} } ...@@ -464,7 +503,7 @@ func (m *BlockPid) Reset() { *m = BlockPid{} }
func (m *BlockPid) String() string { return proto.CompactTextString(m) } func (m *BlockPid) String() string { return proto.CompactTextString(m) }
func (*BlockPid) ProtoMessage() {} func (*BlockPid) ProtoMessage() {}
func (*BlockPid) Descriptor() ([]byte, []int) { func (*BlockPid) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{6} return fileDescriptor_e9ac6287ce250c9a, []int{7}
} }
func (m *BlockPid) XXX_Unmarshal(b []byte) error { func (m *BlockPid) XXX_Unmarshal(b []byte) error {
...@@ -511,7 +550,7 @@ func (m *BlockDetails) Reset() { *m = BlockDetails{} } ...@@ -511,7 +550,7 @@ func (m *BlockDetails) Reset() { *m = BlockDetails{} }
func (m *BlockDetails) String() string { return proto.CompactTextString(m) } func (m *BlockDetails) String() string { return proto.CompactTextString(m) }
func (*BlockDetails) ProtoMessage() {} func (*BlockDetails) ProtoMessage() {}
func (*BlockDetails) Descriptor() ([]byte, []int) { func (*BlockDetails) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{7} return fileDescriptor_e9ac6287ce250c9a, []int{8}
} }
func (m *BlockDetails) XXX_Unmarshal(b []byte) error { func (m *BlockDetails) XXX_Unmarshal(b []byte) error {
...@@ -551,7 +590,7 @@ func (m *Headers) Reset() { *m = Headers{} } ...@@ -551,7 +590,7 @@ func (m *Headers) Reset() { *m = Headers{} }
func (m *Headers) String() string { return proto.CompactTextString(m) } func (m *Headers) String() string { return proto.CompactTextString(m) }
func (*Headers) ProtoMessage() {} func (*Headers) ProtoMessage() {}
func (*Headers) Descriptor() ([]byte, []int) { func (*Headers) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{8} return fileDescriptor_e9ac6287ce250c9a, []int{9}
} }
func (m *Headers) XXX_Unmarshal(b []byte) error { func (m *Headers) XXX_Unmarshal(b []byte) error {
...@@ -591,7 +630,7 @@ func (m *HeadersPid) Reset() { *m = HeadersPid{} } ...@@ -591,7 +630,7 @@ func (m *HeadersPid) Reset() { *m = HeadersPid{} }
func (m *HeadersPid) String() string { return proto.CompactTextString(m) } func (m *HeadersPid) String() string { return proto.CompactTextString(m) }
func (*HeadersPid) ProtoMessage() {} func (*HeadersPid) ProtoMessage() {}
func (*HeadersPid) Descriptor() ([]byte, []int) { func (*HeadersPid) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{9} return fileDescriptor_e9ac6287ce250c9a, []int{10}
} }
func (m *HeadersPid) XXX_Unmarshal(b []byte) error { func (m *HeadersPid) XXX_Unmarshal(b []byte) error {
...@@ -643,7 +682,7 @@ func (m *BlockOverview) Reset() { *m = BlockOverview{} } ...@@ -643,7 +682,7 @@ func (m *BlockOverview) Reset() { *m = BlockOverview{} }
func (m *BlockOverview) String() string { return proto.CompactTextString(m) } func (m *BlockOverview) String() string { return proto.CompactTextString(m) }
func (*BlockOverview) ProtoMessage() {} func (*BlockOverview) ProtoMessage() {}
func (*BlockOverview) Descriptor() ([]byte, []int) { func (*BlockOverview) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{10} return fileDescriptor_e9ac6287ce250c9a, []int{11}
} }
func (m *BlockOverview) XXX_Unmarshal(b []byte) error { func (m *BlockOverview) XXX_Unmarshal(b []byte) error {
...@@ -702,7 +741,7 @@ func (m *BlockDetail) Reset() { *m = BlockDetail{} } ...@@ -702,7 +741,7 @@ func (m *BlockDetail) Reset() { *m = BlockDetail{} }
func (m *BlockDetail) String() string { return proto.CompactTextString(m) } func (m *BlockDetail) String() string { return proto.CompactTextString(m) }
func (*BlockDetail) ProtoMessage() {} func (*BlockDetail) ProtoMessage() {}
func (*BlockDetail) Descriptor() ([]byte, []int) { func (*BlockDetail) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{11} return fileDescriptor_e9ac6287ce250c9a, []int{12}
} }
func (m *BlockDetail) XXX_Unmarshal(b []byte) error { func (m *BlockDetail) XXX_Unmarshal(b []byte) error {
...@@ -762,7 +801,7 @@ func (m *Receipts) Reset() { *m = Receipts{} } ...@@ -762,7 +801,7 @@ func (m *Receipts) Reset() { *m = Receipts{} }
func (m *Receipts) String() string { return proto.CompactTextString(m) } func (m *Receipts) String() string { return proto.CompactTextString(m) }
func (*Receipts) ProtoMessage() {} func (*Receipts) ProtoMessage() {}
func (*Receipts) Descriptor() ([]byte, []int) { func (*Receipts) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{12} return fileDescriptor_e9ac6287ce250c9a, []int{13}
} }
func (m *Receipts) XXX_Unmarshal(b []byte) error { func (m *Receipts) XXX_Unmarshal(b []byte) error {
...@@ -801,7 +840,7 @@ func (m *PrivacyKV) Reset() { *m = PrivacyKV{} } ...@@ -801,7 +840,7 @@ func (m *PrivacyKV) Reset() { *m = PrivacyKV{} }
func (m *PrivacyKV) String() string { return proto.CompactTextString(m) } func (m *PrivacyKV) String() string { return proto.CompactTextString(m) }
func (*PrivacyKV) ProtoMessage() {} func (*PrivacyKV) ProtoMessage() {}
func (*PrivacyKV) Descriptor() ([]byte, []int) { func (*PrivacyKV) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{13} return fileDescriptor_e9ac6287ce250c9a, []int{14}
} }
func (m *PrivacyKV) XXX_Unmarshal(b []byte) error { func (m *PrivacyKV) XXX_Unmarshal(b []byte) error {
...@@ -843,7 +882,7 @@ func (m *PrivacyKVToken) Reset() { *m = PrivacyKVToken{} } ...@@ -843,7 +882,7 @@ func (m *PrivacyKVToken) Reset() { *m = PrivacyKVToken{} }
func (m *PrivacyKVToken) String() string { return proto.CompactTextString(m) } func (m *PrivacyKVToken) String() string { return proto.CompactTextString(m) }
func (*PrivacyKVToken) ProtoMessage() {} func (*PrivacyKVToken) ProtoMessage() {}
func (*PrivacyKVToken) Descriptor() ([]byte, []int) { func (*PrivacyKVToken) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{14} return fileDescriptor_e9ac6287ce250c9a, []int{15}
} }
func (m *PrivacyKVToken) XXX_Unmarshal(b []byte) error { func (m *PrivacyKVToken) XXX_Unmarshal(b []byte) error {
...@@ -904,7 +943,7 @@ func (m *ReceiptsAndPrivacyKV) Reset() { *m = ReceiptsAndPrivacyKV{} } ...@@ -904,7 +943,7 @@ func (m *ReceiptsAndPrivacyKV) Reset() { *m = ReceiptsAndPrivacyKV{} }
func (m *ReceiptsAndPrivacyKV) String() string { return proto.CompactTextString(m) } func (m *ReceiptsAndPrivacyKV) String() string { return proto.CompactTextString(m) }
func (*ReceiptsAndPrivacyKV) ProtoMessage() {} func (*ReceiptsAndPrivacyKV) ProtoMessage() {}
func (*ReceiptsAndPrivacyKV) Descriptor() ([]byte, []int) { func (*ReceiptsAndPrivacyKV) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{15} return fileDescriptor_e9ac6287ce250c9a, []int{16}
} }
func (m *ReceiptsAndPrivacyKV) XXX_Unmarshal(b []byte) error { func (m *ReceiptsAndPrivacyKV) XXX_Unmarshal(b []byte) error {
...@@ -950,7 +989,7 @@ func (m *ReceiptCheckTxList) Reset() { *m = ReceiptCheckTxList{} } ...@@ -950,7 +989,7 @@ func (m *ReceiptCheckTxList) Reset() { *m = ReceiptCheckTxList{} }
func (m *ReceiptCheckTxList) String() string { return proto.CompactTextString(m) } func (m *ReceiptCheckTxList) String() string { return proto.CompactTextString(m) }
func (*ReceiptCheckTxList) ProtoMessage() {} func (*ReceiptCheckTxList) ProtoMessage() {}
func (*ReceiptCheckTxList) Descriptor() ([]byte, []int) { func (*ReceiptCheckTxList) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{16} return fileDescriptor_e9ac6287ce250c9a, []int{17}
} }
func (m *ReceiptCheckTxList) XXX_Unmarshal(b []byte) error { func (m *ReceiptCheckTxList) XXX_Unmarshal(b []byte) error {
...@@ -995,7 +1034,7 @@ func (m *ChainStatus) Reset() { *m = ChainStatus{} } ...@@ -995,7 +1034,7 @@ func (m *ChainStatus) Reset() { *m = ChainStatus{} }
func (m *ChainStatus) String() string { return proto.CompactTextString(m) } func (m *ChainStatus) String() string { return proto.CompactTextString(m) }
func (*ChainStatus) ProtoMessage() {} func (*ChainStatus) ProtoMessage() {}
func (*ChainStatus) Descriptor() ([]byte, []int) { func (*ChainStatus) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{17} return fileDescriptor_e9ac6287ce250c9a, []int{18}
} }
func (m *ChainStatus) XXX_Unmarshal(b []byte) error { func (m *ChainStatus) XXX_Unmarshal(b []byte) error {
...@@ -1056,7 +1095,7 @@ func (m *ReqBlocks) Reset() { *m = ReqBlocks{} } ...@@ -1056,7 +1095,7 @@ func (m *ReqBlocks) Reset() { *m = ReqBlocks{} }
func (m *ReqBlocks) String() string { return proto.CompactTextString(m) } func (m *ReqBlocks) String() string { return proto.CompactTextString(m) }
func (*ReqBlocks) ProtoMessage() {} func (*ReqBlocks) ProtoMessage() {}
func (*ReqBlocks) Descriptor() ([]byte, []int) { func (*ReqBlocks) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{18} return fileDescriptor_e9ac6287ce250c9a, []int{19}
} }
func (m *ReqBlocks) XXX_Unmarshal(b []byte) error { func (m *ReqBlocks) XXX_Unmarshal(b []byte) error {
...@@ -1116,7 +1155,7 @@ func (m *MempoolSize) Reset() { *m = MempoolSize{} } ...@@ -1116,7 +1155,7 @@ func (m *MempoolSize) Reset() { *m = MempoolSize{} }
func (m *MempoolSize) String() string { return proto.CompactTextString(m) } func (m *MempoolSize) String() string { return proto.CompactTextString(m) }
func (*MempoolSize) ProtoMessage() {} func (*MempoolSize) ProtoMessage() {}
func (*MempoolSize) Descriptor() ([]byte, []int) { func (*MempoolSize) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{19} return fileDescriptor_e9ac6287ce250c9a, []int{20}
} }
func (m *MempoolSize) XXX_Unmarshal(b []byte) error { func (m *MempoolSize) XXX_Unmarshal(b []byte) error {
...@@ -1155,7 +1194,7 @@ func (m *ReplyBlockHeight) Reset() { *m = ReplyBlockHeight{} } ...@@ -1155,7 +1194,7 @@ func (m *ReplyBlockHeight) Reset() { *m = ReplyBlockHeight{} }
func (m *ReplyBlockHeight) String() string { return proto.CompactTextString(m) } func (m *ReplyBlockHeight) String() string { return proto.CompactTextString(m) }
func (*ReplyBlockHeight) ProtoMessage() {} func (*ReplyBlockHeight) ProtoMessage() {}
func (*ReplyBlockHeight) Descriptor() ([]byte, []int) { func (*ReplyBlockHeight) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{20} return fileDescriptor_e9ac6287ce250c9a, []int{21}
} }
func (m *ReplyBlockHeight) XXX_Unmarshal(b []byte) error { func (m *ReplyBlockHeight) XXX_Unmarshal(b []byte) error {
...@@ -1200,7 +1239,7 @@ func (m *BlockBody) Reset() { *m = BlockBody{} } ...@@ -1200,7 +1239,7 @@ func (m *BlockBody) Reset() { *m = BlockBody{} }
func (m *BlockBody) String() string { return proto.CompactTextString(m) } func (m *BlockBody) String() string { return proto.CompactTextString(m) }
func (*BlockBody) ProtoMessage() {} func (*BlockBody) ProtoMessage() {}
func (*BlockBody) Descriptor() ([]byte, []int) { func (*BlockBody) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{21} return fileDescriptor_e9ac6287ce250c9a, []int{22}
} }
func (m *BlockBody) XXX_Unmarshal(b []byte) error { func (m *BlockBody) XXX_Unmarshal(b []byte) error {
...@@ -1261,7 +1300,7 @@ func (m *IsCaughtUp) Reset() { *m = IsCaughtUp{} } ...@@ -1261,7 +1300,7 @@ func (m *IsCaughtUp) Reset() { *m = IsCaughtUp{} }
func (m *IsCaughtUp) String() string { return proto.CompactTextString(m) } func (m *IsCaughtUp) String() string { return proto.CompactTextString(m) }
func (*IsCaughtUp) ProtoMessage() {} func (*IsCaughtUp) ProtoMessage() {}
func (*IsCaughtUp) Descriptor() ([]byte, []int) { func (*IsCaughtUp) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{22} return fileDescriptor_e9ac6287ce250c9a, []int{23}
} }
func (m *IsCaughtUp) XXX_Unmarshal(b []byte) error { func (m *IsCaughtUp) XXX_Unmarshal(b []byte) error {
...@@ -1301,7 +1340,7 @@ func (m *IsNtpClockSync) Reset() { *m = IsNtpClockSync{} } ...@@ -1301,7 +1340,7 @@ func (m *IsNtpClockSync) Reset() { *m = IsNtpClockSync{} }
func (m *IsNtpClockSync) String() string { return proto.CompactTextString(m) } func (m *IsNtpClockSync) String() string { return proto.CompactTextString(m) }
func (*IsNtpClockSync) ProtoMessage() {} func (*IsNtpClockSync) ProtoMessage() {}
func (*IsNtpClockSync) Descriptor() ([]byte, []int) { func (*IsNtpClockSync) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{23} return fileDescriptor_e9ac6287ce250c9a, []int{24}
} }
func (m *IsNtpClockSync) XXX_Unmarshal(b []byte) error { func (m *IsNtpClockSync) XXX_Unmarshal(b []byte) error {
...@@ -1345,7 +1384,7 @@ func (m *ChainExecutor) Reset() { *m = ChainExecutor{} } ...@@ -1345,7 +1384,7 @@ func (m *ChainExecutor) Reset() { *m = ChainExecutor{} }
func (m *ChainExecutor) String() string { return proto.CompactTextString(m) } func (m *ChainExecutor) String() string { return proto.CompactTextString(m) }
func (*ChainExecutor) ProtoMessage() {} func (*ChainExecutor) ProtoMessage() {}
func (*ChainExecutor) Descriptor() ([]byte, []int) { func (*ChainExecutor) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{24} return fileDescriptor_e9ac6287ce250c9a, []int{25}
} }
func (m *ChainExecutor) XXX_Unmarshal(b []byte) error { func (m *ChainExecutor) XXX_Unmarshal(b []byte) error {
...@@ -1414,7 +1453,7 @@ func (m *BlockSequence) Reset() { *m = BlockSequence{} } ...@@ -1414,7 +1453,7 @@ func (m *BlockSequence) Reset() { *m = BlockSequence{} }
func (m *BlockSequence) String() string { return proto.CompactTextString(m) } func (m *BlockSequence) String() string { return proto.CompactTextString(m) }
func (*BlockSequence) ProtoMessage() {} func (*BlockSequence) ProtoMessage() {}
func (*BlockSequence) Descriptor() ([]byte, []int) { func (*BlockSequence) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{25} return fileDescriptor_e9ac6287ce250c9a, []int{26}
} }
func (m *BlockSequence) XXX_Unmarshal(b []byte) error { func (m *BlockSequence) XXX_Unmarshal(b []byte) error {
...@@ -1461,7 +1500,7 @@ func (m *BlockSequences) Reset() { *m = BlockSequences{} } ...@@ -1461,7 +1500,7 @@ func (m *BlockSequences) Reset() { *m = BlockSequences{} }
func (m *BlockSequences) String() string { return proto.CompactTextString(m) } func (m *BlockSequences) String() string { return proto.CompactTextString(m) }
func (*BlockSequences) ProtoMessage() {} func (*BlockSequences) ProtoMessage() {}
func (*BlockSequences) Descriptor() ([]byte, []int) { func (*BlockSequences) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{26} return fileDescriptor_e9ac6287ce250c9a, []int{27}
} }
func (m *BlockSequences) XXX_Unmarshal(b []byte) error { func (m *BlockSequences) XXX_Unmarshal(b []byte) error {
...@@ -1504,7 +1543,7 @@ func (m *ParaChainBlockDetail) Reset() { *m = ParaChainBlockDetail{} } ...@@ -1504,7 +1543,7 @@ func (m *ParaChainBlockDetail) Reset() { *m = ParaChainBlockDetail{} }
func (m *ParaChainBlockDetail) String() string { return proto.CompactTextString(m) } func (m *ParaChainBlockDetail) String() string { return proto.CompactTextString(m) }
func (*ParaChainBlockDetail) ProtoMessage() {} func (*ParaChainBlockDetail) ProtoMessage() {}
func (*ParaChainBlockDetail) Descriptor() ([]byte, []int) { func (*ParaChainBlockDetail) Descriptor() ([]byte, []int) {
return fileDescriptor_e9ac6287ce250c9a, []int{27} return fileDescriptor_e9ac6287ce250c9a, []int{28}
} }
func (m *ParaChainBlockDetail) XXX_Unmarshal(b []byte) error { func (m *ParaChainBlockDetail) XXX_Unmarshal(b []byte) error {
...@@ -1546,6 +1585,7 @@ func init() { ...@@ -1546,6 +1585,7 @@ func init() {
proto.RegisterType((*BlockSeqCB)(nil), "types.BlockSeqCB") proto.RegisterType((*BlockSeqCB)(nil), "types.BlockSeqCB")
proto.RegisterType((*BlockSeqCBs)(nil), "types.BlockSeqCBs") proto.RegisterType((*BlockSeqCBs)(nil), "types.BlockSeqCBs")
proto.RegisterType((*BlockSeq)(nil), "types.BlockSeq") proto.RegisterType((*BlockSeq)(nil), "types.BlockSeq")
proto.RegisterType((*BlockSeqs)(nil), "types.BlockSeqs")
proto.RegisterType((*BlockPid)(nil), "types.BlockPid") proto.RegisterType((*BlockPid)(nil), "types.BlockPid")
proto.RegisterType((*BlockDetails)(nil), "types.BlockDetails") proto.RegisterType((*BlockDetails)(nil), "types.BlockDetails")
proto.RegisterType((*Headers)(nil), "types.Headers") proto.RegisterType((*Headers)(nil), "types.Headers")
...@@ -1573,76 +1613,77 @@ func init() { ...@@ -1573,76 +1613,77 @@ func init() {
func init() { proto.RegisterFile("blockchain.proto", fileDescriptor_e9ac6287ce250c9a) } func init() { proto.RegisterFile("blockchain.proto", fileDescriptor_e9ac6287ce250c9a) }
var fileDescriptor_e9ac6287ce250c9a = []byte{ var fileDescriptor_e9ac6287ce250c9a = []byte{
// 1135 bytes of a gzipped FileDescriptorProto // 1151 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x56, 0xdd, 0x6e, 0x1b, 0x45, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x56, 0xdd, 0x6e, 0x1b, 0x45,
0x14, 0xd6, 0xfa, 0x2f, 0xf6, 0xf1, 0x0f, 0xe9, 0xc8, 0x20, 0x2b, 0x02, 0xea, 0x0e, 0x55, 0xb1, 0x14, 0xd6, 0xfa, 0x2f, 0xf6, 0xf1, 0x0f, 0xe9, 0xc8, 0x20, 0x2b, 0x02, 0xea, 0x0e, 0x55, 0xb1,
0x42, 0xe5, 0x48, 0x09, 0x2a, 0xbd, 0x00, 0x09, 0xe2, 0x20, 0x25, 0x4d, 0x29, 0x61, 0x92, 0xe6, 0x42, 0xe5, 0xa0, 0x04, 0x95, 0x5e, 0x80, 0x04, 0x71, 0x90, 0x92, 0xa6, 0x94, 0x30, 0x49, 0x73,
0x82, 0xbb, 0xc9, 0x7a, 0x92, 0x5d, 0xc5, 0xfb, 0x93, 0x9d, 0x59, 0xe3, 0xe5, 0x1d, 0x78, 0x04, 0xc1, 0xdd, 0x64, 0x3d, 0xc9, 0xae, 0xe2, 0xfd, 0xc9, 0xce, 0xac, 0xf1, 0xf2, 0x0e, 0x3c, 0x02,
0x5e, 0x00, 0xf1, 0x4e, 0xbc, 0x0a, 0x9a, 0x33, 0xb3, 0xde, 0x5d, 0x93, 0x14, 0xf5, 0xb2, 0x77, 0x2f, 0x80, 0x78, 0x27, 0x5e, 0x05, 0xcd, 0x99, 0x59, 0xef, 0xae, 0x49, 0x8a, 0x7a, 0xc9, 0xdd,
0xe7, 0xff, 0x3b, 0xe7, 0xcc, 0xcc, 0x39, 0x03, 0xdb, 0x57, 0x8b, 0xc8, 0xbd, 0x75, 0x3d, 0xee, 0x9c, 0xff, 0xef, 0x9c, 0x33, 0x73, 0xce, 0xc0, 0xf6, 0xd5, 0x22, 0x72, 0x6f, 0x5d, 0x8f, 0xfb,
0x87, 0xd3, 0x38, 0x89, 0x54, 0x44, 0x9a, 0x2a, 0x8b, 0x85, 0xdc, 0x79, 0xa4, 0x12, 0x1e, 0x4a, 0xe1, 0x34, 0x4e, 0x22, 0x15, 0x91, 0xa6, 0xca, 0x62, 0x21, 0x77, 0x1e, 0xa9, 0x84, 0x87, 0x92,
0xee, 0x2a, 0x3f, 0xb2, 0x9a, 0x9d, 0x9e, 0x1b, 0x05, 0x41, 0xce, 0xd1, 0xbf, 0x6b, 0xd0, 0x3a, 0xbb, 0xca, 0x8f, 0xac, 0x64, 0xa7, 0xe7, 0x46, 0x41, 0x90, 0x53, 0xf4, 0xaf, 0x1a, 0xb4, 0x8e,
0x16, 0x7c, 0x2e, 0x12, 0x32, 0x82, 0xad, 0xa5, 0x48, 0xa4, 0x1f, 0x85, 0x23, 0x67, 0xec, 0x4c, 0x05, 0x9f, 0x8b, 0x84, 0x8c, 0x60, 0x6b, 0x29, 0x12, 0xe9, 0x47, 0xe1, 0xc8, 0x19, 0x3b, 0x93,
0xea, 0x2c, 0x67, 0xc9, 0xe7, 0x00, 0x31, 0x4f, 0x44, 0xa8, 0x8e, 0xb9, 0xf4, 0x46, 0xb5, 0xb1, 0x3a, 0xcb, 0x49, 0xf2, 0x29, 0x40, 0xcc, 0x13, 0x11, 0xaa, 0x63, 0x2e, 0xbd, 0x51, 0x6d, 0xec,
0x33, 0xe9, 0xb1, 0x92, 0x84, 0x7c, 0x02, 0x2d, 0xb5, 0x42, 0x5d, 0x1d, 0x75, 0x96, 0x23, 0x9f, 0x4c, 0x7a, 0xac, 0xc4, 0x21, 0x1f, 0x41, 0x4b, 0xad, 0x50, 0x56, 0x47, 0x99, 0xa5, 0xc8, 0xc7,
0x42, 0x47, 0x2a, 0xae, 0x04, 0xaa, 0x1a, 0xa8, 0x2a, 0x04, 0xda, 0xcb, 0x13, 0xfe, 0x8d, 0xa7, 0xd0, 0x91, 0x8a, 0x2b, 0x81, 0xa2, 0x06, 0x8a, 0x0a, 0x86, 0xb6, 0xf2, 0x84, 0x7f, 0xe3, 0xa9,
0x46, 0x4d, 0x84, 0xb3, 0x9c, 0xf6, 0xc2, 0x72, 0x2e, 0xfc, 0x40, 0x8c, 0x5a, 0xa8, 0x2a, 0x04, 0x51, 0x13, 0xc3, 0x59, 0x4a, 0x5b, 0x61, 0x3a, 0x17, 0x7e, 0x20, 0x46, 0x2d, 0x14, 0x15, 0x0c,
0x3a, 0x4b, 0xb5, 0x9a, 0x45, 0x69, 0xa8, 0x46, 0x1d, 0x93, 0xa5, 0x65, 0x09, 0x81, 0x86, 0xa7, 0x8d, 0x52, 0xad, 0x66, 0x51, 0x1a, 0xaa, 0x51, 0xc7, 0xa0, 0xb4, 0x24, 0x21, 0xd0, 0xf0, 0x74,
0x81, 0x00, 0x81, 0x90, 0xd6, 0x99, 0xcf, 0xfd, 0xeb, 0x6b, 0xdf, 0x4d, 0x17, 0x2a, 0x1b, 0x75, 0x20, 0xc0, 0x40, 0x78, 0xd6, 0xc8, 0xe7, 0xfe, 0xf5, 0xb5, 0xef, 0xa6, 0x0b, 0x95, 0x8d, 0xba,
0xc7, 0xce, 0xa4, 0xcf, 0x4a, 0x12, 0x32, 0x85, 0x8e, 0xf4, 0x6f, 0x42, 0xae, 0xd2, 0x44, 0x8c, 0x63, 0x67, 0xd2, 0x67, 0x25, 0x0e, 0x99, 0x42, 0x47, 0xfa, 0x37, 0x21, 0x57, 0x69, 0x22, 0x46,
0xda, 0x63, 0x67, 0xd2, 0xdd, 0xdf, 0x9e, 0x62, 0xeb, 0xa6, 0xe7, 0xb9, 0x9c, 0x15, 0x26, 0xf4, 0xed, 0xb1, 0x33, 0xe9, 0xee, 0x6f, 0x4f, 0xb1, 0x74, 0xd3, 0xf3, 0x9c, 0xcf, 0x0a, 0x15, 0xfa,
0x9f, 0x1a, 0x34, 0x0f, 0x75, 0x2e, 0x1f, 0x48, 0xb7, 0xfe, 0xaf, 0xfe, 0x1d, 0x68, 0x07, 0xdc, 0x77, 0x0d, 0x9a, 0x87, 0x1a, 0xcb, 0xff, 0xa4, 0x5a, 0xff, 0x95, 0xff, 0x0e, 0xb4, 0x03, 0xee,
0x0f, 0x11, 0xb2, 0x87, 0x90, 0x6b, 0x5e, 0xfb, 0x22, 0x6d, 0x50, 0xfb, 0x18, 0xba, 0x24, 0x79, 0x87, 0x18, 0xb2, 0x87, 0x21, 0xd7, 0xb4, 0xb6, 0xc5, 0xb3, 0x89, 0xda, 0x47, 0xd7, 0x25, 0xce,
0xdf, 0xde, 0x91, 0xa7, 0x50, 0x57, 0x2b, 0x39, 0xda, 0x1a, 0xd7, 0x27, 0xdd, 0x7d, 0x62, 0x2d, 0xfb, 0xd6, 0x8e, 0x3c, 0x85, 0xba, 0x5a, 0xc9, 0xd1, 0xd6, 0xb8, 0x3e, 0xe9, 0xee, 0x13, 0xab,
0x2f, 0x8a, 0xfb, 0xc9, 0xb4, 0x9a, 0x3e, 0x87, 0x16, 0x36, 0x58, 0x12, 0x0a, 0x4d, 0x5f, 0x89, 0x79, 0x51, 0xdc, 0x4f, 0xa6, 0xc5, 0xf4, 0x39, 0xb4, 0xb0, 0xc0, 0x92, 0x50, 0x68, 0xfa, 0x4a,
0x40, 0x8e, 0x1c, 0xf4, 0xe8, 0x59, 0x0f, 0xd4, 0x32, 0xa3, 0xa2, 0xaf, 0x00, 0x90, 0x3f, 0x17, 0x04, 0x72, 0xe4, 0xa0, 0x45, 0xcf, 0x5a, 0xa0, 0x94, 0x19, 0x11, 0x7d, 0x05, 0x80, 0xf4, 0xb9,
0x77, 0xb3, 0x43, 0x7d, 0x03, 0x42, 0x1e, 0x08, 0x3c, 0x90, 0x0e, 0x43, 0x9a, 0x6c, 0x43, 0xfd, 0xb8, 0x9b, 0x1d, 0xea, 0x1b, 0x10, 0xf2, 0x40, 0x60, 0x43, 0x3a, 0x0c, 0xcf, 0x64, 0x1b, 0xea,
0x2d, 0x7b, 0x8d, 0xc7, 0xd0, 0x61, 0x9a, 0xd4, 0x9d, 0x14, 0xa1, 0x1b, 0xcd, 0x05, 0xf6, 0xbf, 0x6f, 0xd9, 0x6b, 0x6c, 0x43, 0x87, 0xe9, 0xa3, 0xae, 0xa4, 0x08, 0xdd, 0x68, 0x2e, 0xb0, 0xfe,
0xc3, 0x2c, 0x47, 0x5f, 0x40, 0xb7, 0x88, 0x25, 0xc9, 0x97, 0x55, 0xf8, 0x47, 0x65, 0x78, 0x34, 0x1d, 0x66, 0x29, 0xfa, 0x02, 0xba, 0x85, 0x2f, 0x49, 0x3e, 0xaf, 0x86, 0x7f, 0x54, 0x0e, 0x8f,
0xc9, 0x73, 0x88, 0xa1, 0x9d, 0x0b, 0x35, 0x5a, 0x98, 0x06, 0xf6, 0x46, 0x68, 0x92, 0x3c, 0x83, 0x2a, 0x39, 0x86, 0x18, 0xda, 0x39, 0x53, 0x47, 0x0b, 0xd3, 0xc0, 0xde, 0x08, 0x7d, 0x24, 0xcf,
0xba, 0x14, 0x77, 0x88, 0xdf, 0xdd, 0x1f, 0x6e, 0x04, 0x49, 0x45, 0xe8, 0x0a, 0xa6, 0x0d, 0xc8, 0xa0, 0x2e, 0xc5, 0x1d, 0xc6, 0xef, 0xee, 0x0f, 0x37, 0x9c, 0xa4, 0x22, 0x74, 0x05, 0xd3, 0x0a,
0x2e, 0xb4, 0xe6, 0x42, 0x71, 0x7f, 0x81, 0x59, 0x15, 0x0d, 0x42, 0xd3, 0x23, 0xd4, 0x30, 0x6b, 0x64, 0x17, 0x5a, 0x73, 0xa1, 0xb8, 0xbf, 0x40, 0x54, 0x45, 0x81, 0x50, 0xf5, 0x08, 0x25, 0xcc,
0x41, 0xbf, 0xb7, 0x88, 0x67, 0xfe, 0x5c, 0x23, 0xc6, 0xfe, 0xdc, 0x96, 0xac, 0x49, 0xdd, 0x37, 0x6a, 0xd0, 0x2f, 0xa1, 0x93, 0x7b, 0x90, 0xe4, 0x33, 0x68, 0x48, 0x71, 0x97, 0xc3, 0xfc, 0x60,
0xbc, 0x00, 0x16, 0x73, 0xa3, 0x6f, 0xa8, 0xa2, 0x2f, 0xa1, 0x57, 0x0a, 0x2c, 0xc9, 0xa4, 0x5a, 0x23, 0x02, 0x43, 0x21, 0xfd, 0xce, 0x62, 0x3c, 0xf3, 0xe7, 0x1a, 0x63, 0xec, 0xcf, 0x6d, 0x91,
0xec, 0x7d, 0xe0, 0xb6, 0xda, 0x29, 0x6c, 0x99, 0x79, 0x21, 0xc9, 0x17, 0x55, 0xa7, 0xbe, 0x75, 0xf4, 0x51, 0x57, 0x1a, 0xaf, 0x8c, 0x45, 0xb9, 0x51, 0x69, 0x14, 0xd1, 0x97, 0xd0, 0x2b, 0x41,
0x32, 0xea, 0xdc, 0xfe, 0x18, 0xc0, 0xda, 0xdf, 0x9f, 0xed, 0x04, 0xb6, 0x3c, 0xa3, 0xb7, 0xf9, 0x91, 0x64, 0x52, 0x2d, 0xcf, 0x7d, 0x70, 0x6d, 0x7d, 0xa6, 0xb0, 0x65, 0x26, 0x8c, 0xc6, 0x5a,
0x0e, 0x2a, 0x61, 0x24, 0xcb, 0xd5, 0xd4, 0x83, 0x3e, 0xe6, 0xf3, 0xf3, 0x52, 0x24, 0x4b, 0x5f, 0x31, 0xea, 0x5b, 0x23, 0x23, 0xce, 0xf5, 0x8f, 0x01, 0xac, 0xfe, 0xfd, 0x68, 0x27, 0xb0, 0xe5,
0xfc, 0x46, 0x9e, 0x40, 0x43, 0xeb, 0x30, 0xda, 0x7f, 0xe0, 0x51, 0x55, 0x9e, 0x16, 0xb5, 0xea, 0x19, 0xb9, 0xc5, 0x3b, 0xa8, 0xb8, 0x91, 0x2c, 0x17, 0x53, 0x0f, 0xfa, 0x88, 0xe7, 0xa7, 0xa5,
0xb4, 0xd8, 0x81, 0xb6, 0x79, 0x77, 0x42, 0x8e, 0xea, 0xe3, 0xba, 0xbe, 0xf9, 0x39, 0x4f, 0xff, 0x48, 0x96, 0xbe, 0xf8, 0x95, 0x3c, 0x81, 0x86, 0x96, 0xa1, 0xb7, 0x7f, 0x85, 0x47, 0x51, 0x79,
0x72, 0xec, 0x55, 0x30, 0xa5, 0x17, 0x1d, 0x75, 0x1e, 0xec, 0x28, 0x99, 0x42, 0x3b, 0x11, 0xae, 0xbe, 0xd4, 0xaa, 0xf3, 0x65, 0x07, 0xda, 0xe6, 0xa5, 0x0a, 0x39, 0xaa, 0x8f, 0xeb, 0xfa, 0xad,
0xf0, 0x63, 0xa5, 0x0b, 0x29, 0x37, 0x91, 0x19, 0xf1, 0x11, 0x57, 0x9c, 0xad, 0x6d, 0xc8, 0x63, 0xe4, 0x34, 0xfd, 0xd3, 0xb1, 0x97, 0xc7, 0xa4, 0x5e, 0x54, 0xd4, 0x79, 0xb0, 0xa2, 0x64, 0x0a,
0xa8, 0x9d, 0x5e, 0x22, 0x72, 0x77, 0xff, 0x23, 0x6b, 0x79, 0x2a, 0xb2, 0x4b, 0xbe, 0x48, 0x05, 0xed, 0x44, 0xb8, 0xc2, 0x8f, 0x95, 0x4e, 0xa4, 0x5c, 0x44, 0x66, 0xd8, 0x47, 0x5c, 0x71, 0xb6,
0xab, 0x9d, 0x5e, 0x92, 0x67, 0x30, 0x88, 0x13, 0xb1, 0x3c, 0x57, 0x5c, 0xa5, 0xb2, 0x34, 0x13, 0xd6, 0x21, 0x8f, 0xa1, 0x76, 0x7a, 0x89, 0x91, 0x8b, 0x36, 0x9f, 0x8a, 0xec, 0x92, 0x2f, 0x52,
0x36, 0xa4, 0xf4, 0x05, 0xb4, 0x59, 0x1e, 0x74, 0xb7, 0x94, 0x84, 0x39, 0x94, 0x41, 0x35, 0x89, 0xc1, 0x6a, 0xa7, 0x97, 0xe4, 0x19, 0x0c, 0xe2, 0x44, 0x2c, 0xcf, 0x15, 0x57, 0xa9, 0x2c, 0x4d,
0x22, 0x01, 0xfa, 0x0a, 0x3a, 0x67, 0x89, 0xbf, 0xe4, 0x6e, 0x76, 0x7a, 0x49, 0xbe, 0xd3, 0x60, 0x91, 0x0d, 0x2e, 0x7d, 0x01, 0x6d, 0x96, 0x3b, 0xdd, 0x2d, 0x81, 0x30, 0x4d, 0x19, 0x54, 0x41,
0x96, 0xb9, 0x88, 0x6e, 0x45, 0x68, 0xdd, 0x3f, 0xb6, 0xee, 0x67, 0x15, 0x25, 0xdb, 0x30, 0xa6, 0x14, 0x00, 0xe8, 0x2b, 0xe8, 0x9c, 0x25, 0xfe, 0x92, 0xbb, 0xd9, 0xe9, 0x25, 0xf9, 0x56, 0x07,
0x19, 0x0c, 0xaa, 0x16, 0x64, 0x08, 0x4d, 0x65, 0xe3, 0xe8, 0xa3, 0x36, 0x8c, 0x39, 0x8e, 0x93, 0xb3, 0xc4, 0x45, 0x74, 0x2b, 0x42, 0x6b, 0xfe, 0xa1, 0x35, 0x3f, 0xab, 0x08, 0xd9, 0x86, 0x32,
0x70, 0x2e, 0x56, 0x78, 0x1c, 0x4d, 0x96, 0xb3, 0x66, 0x28, 0x7a, 0x95, 0xa1, 0x88, 0x03, 0xdc, 0xcd, 0x60, 0x50, 0xd5, 0x20, 0x43, 0x68, 0x2a, 0xeb, 0x47, 0xb7, 0xda, 0x10, 0xa6, 0x1d, 0x27,
0xb4, 0xa9, 0xf1, 0x60, 0x9b, 0xa8, 0x84, 0x61, 0x5e, 0xfe, 0x0f, 0xe1, 0xbc, 0xa8, 0xe8, 0xab, 0xe1, 0x5c, 0xac, 0xb0, 0x1d, 0x4d, 0x96, 0x93, 0x66, 0x8c, 0x7a, 0x95, 0x31, 0x8a, 0x23, 0xdf,
0x4a, 0x2b, 0x9c, 0x92, 0x7b, 0x6e, 0x5e, 0x3a, 0x8c, 0x29, 0x74, 0xd6, 0x15, 0xd9, 0x6b, 0xb8, 0x94, 0xa9, 0xf1, 0x60, 0x99, 0xa8, 0x84, 0x61, 0x9e, 0xfe, 0xf7, 0xe1, 0xbc, 0xc8, 0xe8, 0x8b,
0xbd, 0x59, 0x39, 0x2b, 0x4c, 0xe8, 0x04, 0x88, 0x8d, 0x32, 0xf3, 0x84, 0x7b, 0x7b, 0xb1, 0x7a, 0x4a, 0x29, 0x9c, 0x92, 0x79, 0xae, 0x5e, 0x6a, 0xc6, 0x14, 0x3a, 0xeb, 0x8c, 0xec, 0x35, 0xdc,
0xed, 0x4b, 0x5c, 0x40, 0x22, 0x49, 0x4c, 0xe7, 0x3b, 0x0c, 0x69, 0x9a, 0x41, 0x77, 0xa6, 0xd7, 0xde, 0xcc, 0x9c, 0x15, 0x2a, 0x74, 0x02, 0xc4, 0x7a, 0x99, 0x79, 0xc2, 0xbd, 0xbd, 0x58, 0xbd,
0xb2, 0x39, 0x30, 0xf2, 0x14, 0xfa, 0x6e, 0x9a, 0xe0, 0x2a, 0x30, 0x63, 0xd5, 0x4c, 0x8a, 0xaa, 0xf6, 0x25, 0xae, 0x2c, 0x91, 0x24, 0xa6, 0xf2, 0x1d, 0x86, 0x67, 0x9a, 0x41, 0x77, 0xa6, 0x17,
0x90, 0x8c, 0xa1, 0x1b, 0x88, 0x20, 0x8e, 0xa2, 0xc5, 0xb9, 0xff, 0xbb, 0xb0, 0x37, 0xb7, 0x2c, 0xb9, 0x69, 0x18, 0x79, 0x0a, 0x7d, 0x37, 0x4d, 0x70, 0x79, 0x98, 0x41, 0x6c, 0x66, 0x4b, 0x95,
0x22, 0x14, 0x7a, 0x81, 0xbc, 0xf9, 0x25, 0x15, 0xa9, 0x40, 0x93, 0x3a, 0x9a, 0x54, 0x64, 0x94, 0x49, 0xc6, 0xd0, 0x0d, 0x44, 0x10, 0x47, 0xd1, 0xe2, 0xdc, 0xff, 0x4d, 0xd8, 0x9b, 0x5b, 0x66,
0x43, 0x87, 0x89, 0x3b, 0x3b, 0x4c, 0x87, 0xd0, 0x94, 0x8a, 0x27, 0x39, 0xa0, 0x61, 0xf4, 0x73, 0x11, 0x0a, 0xbd, 0x40, 0xde, 0xfc, 0x9c, 0x8a, 0x54, 0xa0, 0x4a, 0x1d, 0x55, 0x2a, 0x3c, 0xca,
0x14, 0xe1, 0xdc, 0x02, 0x68, 0x52, 0x3f, 0x0b, 0x5f, 0x1e, 0x15, 0x83, 0xa8, 0xcd, 0xd6, 0x7c, 0xa1, 0xc3, 0xc4, 0x9d, 0x1d, 0xbf, 0x43, 0x68, 0x4a, 0xc5, 0x93, 0x3c, 0xa0, 0x21, 0xf4, 0x73,
0xfe, 0x78, 0x1b, 0x58, 0x9e, 0x26, 0xe9, 0x13, 0xe8, 0xfe, 0x54, 0xca, 0x8a, 0x40, 0x43, 0xea, 0x14, 0xe1, 0xdc, 0x06, 0xd0, 0x47, 0xfd, 0x2c, 0x7c, 0x79, 0x54, 0x8c, 0xae, 0x36, 0x5b, 0xd3,
0x6c, 0x0c, 0x06, 0xd2, 0x74, 0x17, 0xb6, 0x99, 0x88, 0x17, 0x19, 0xe6, 0x61, 0xeb, 0x2b, 0x76, 0xf9, 0xe3, 0x6d, 0x60, 0x7a, 0xfa, 0x48, 0x9f, 0x40, 0xf7, 0xc7, 0x12, 0x2a, 0x02, 0x0d, 0xa9,
0x99, 0x53, 0xde, 0x65, 0xf4, 0x4f, 0x07, 0x3a, 0x68, 0x77, 0x18, 0xcd, 0xb3, 0x7c, 0x5f, 0x38, 0xd1, 0x98, 0x18, 0x78, 0xa6, 0xbb, 0xb0, 0xcd, 0x44, 0xbc, 0xc8, 0x10, 0x87, 0xcd, 0xaf, 0xd8,
0xef, 0xdc, 0x17, 0xef, 0xfd, 0xee, 0xca, 0x1b, 0xaf, 0xfe, 0xce, 0x8d, 0xd7, 0xd8, 0xdc, 0x78, 0x7e, 0x4e, 0x79, 0xfb, 0xd1, 0x3f, 0x1c, 0x3b, 0x0a, 0x0f, 0xa3, 0x79, 0x96, 0x6f, 0x18, 0xe7,
0xf4, 0x39, 0xc0, 0x89, 0x9c, 0xf1, 0xf4, 0xc6, 0x53, 0x6f, 0x63, 0x6d, 0x7d, 0x22, 0x5d, 0xe4, 0x9d, 0x1b, 0xe6, 0xbd, 0xdf, 0x5d, 0x79, 0x47, 0xd6, 0xdf, 0xb9, 0x23, 0x1b, 0x9b, 0x3b, 0x92,
0xd2, 0x18, 0x2b, 0x69, 0xb3, 0x92, 0x84, 0xbe, 0x84, 0xc1, 0x89, 0x7c, 0xa3, 0xe2, 0x19, 0x0e, 0x3e, 0x07, 0x38, 0x91, 0x33, 0x9e, 0xde, 0x78, 0xea, 0x6d, 0xac, 0xb5, 0x4f, 0xa4, 0x8b, 0x54,
0xfb, 0x2c, 0x74, 0xf5, 0x93, 0xf6, 0x65, 0xa8, 0x62, 0x17, 0xcf, 0x24, 0x0b, 0x5d, 0xeb, 0xb5, 0x1a, 0x63, 0x26, 0x6d, 0x56, 0xe2, 0xd0, 0x97, 0x30, 0x38, 0x91, 0x6f, 0x54, 0x3c, 0xc3, 0xe1,
0x21, 0xa5, 0x7f, 0x38, 0xd0, 0xc7, 0x5b, 0xf3, 0xe3, 0x4a, 0xb8, 0xa9, 0x8a, 0x12, 0xdd, 0xb1, 0x9d, 0x85, 0xae, 0x7e, 0xd2, 0xbe, 0x0c, 0x55, 0xec, 0x62, 0x4f, 0xb2, 0xd0, 0xb5, 0x56, 0x1b,
0x79, 0xe2, 0x2f, 0x45, 0x62, 0xdf, 0x93, 0xe5, 0x74, 0x35, 0xd7, 0x69, 0xe8, 0xbe, 0xd1, 0x5b, 0x5c, 0xfa, 0xbb, 0x03, 0x7d, 0xbc, 0x35, 0x3f, 0xac, 0x84, 0x9b, 0xaa, 0x28, 0xd1, 0x15, 0x9b,
0xcf, 0xac, 0xb8, 0x35, 0x5f, 0xfd, 0x4f, 0xd4, 0x37, 0xff, 0x13, 0x43, 0x68, 0xc6, 0x3c, 0xe1, 0x27, 0xfe, 0x52, 0x24, 0xf6, 0x3d, 0x59, 0x4a, 0x67, 0x73, 0x9d, 0x86, 0xee, 0x1b, 0xbd, 0x27,
0x81, 0x9d, 0x2a, 0x86, 0xd1, 0x52, 0xb1, 0x52, 0x09, 0xc7, 0x4f, 0x46, 0x8f, 0x19, 0x86, 0x7e, 0xcd, 0x52, 0x5c, 0xd3, 0xd5, 0x1f, 0x48, 0x7d, 0xf3, 0x07, 0x32, 0x84, 0x66, 0xcc, 0x13, 0x1e,
0x63, 0x27, 0x6f, 0xbe, 0xb1, 0xf4, 0x41, 0x63, 0x54, 0xc7, 0x7c, 0xb5, 0x30, 0x20, 0x81, 0xc6, 0xd8, 0xa9, 0x62, 0x08, 0xcd, 0x15, 0x2b, 0x95, 0x70, 0xfc, 0x96, 0xf4, 0x98, 0x21, 0xe8, 0xd7,
0x45, 0x16, 0xe7, 0xb7, 0x15, 0x69, 0xfa, 0x2d, 0x0c, 0x2a, 0x8e, 0x7a, 0x42, 0x55, 0x76, 0xc6, 0x76, 0xf2, 0xe6, 0x3b, 0x4e, 0x37, 0x1a, 0xbd, 0x3a, 0xe6, 0x73, 0x86, 0x0e, 0x09, 0x34, 0x2e,
0xfd, 0x0b, 0xd1, 0xae, 0x0e, 0x0f, 0x86, 0x67, 0x3c, 0xe1, 0xd8, 0x89, 0xf2, 0x38, 0xfe, 0x1a, 0xb2, 0x38, 0xbf, 0xad, 0x78, 0xa6, 0xdf, 0xc0, 0xa0, 0x62, 0xa8, 0x27, 0x54, 0x65, 0x67, 0xdc,
0xba, 0x38, 0x73, 0xed, 0xbe, 0x74, 0x1e, 0xdc, 0x97, 0x65, 0x33, 0xdd, 0x2a, 0x69, 0x01, 0x6c, 0xbf, 0x42, 0xed, 0xea, 0xf0, 0x60, 0x78, 0xc6, 0x13, 0x8e, 0x95, 0x28, 0x8f, 0xe3, 0xaf, 0xa0,
0x8e, 0x6b, 0xfe, 0xf0, 0xf1, 0xaf, 0x9f, 0xdd, 0xf8, 0xca, 0x4b, 0xaf, 0xa6, 0x6e, 0x14, 0xec, 0x8b, 0x33, 0xd7, 0x6e, 0x58, 0xe7, 0xc1, 0x0d, 0x5b, 0x56, 0xd3, 0xa5, 0x92, 0x36, 0x80, 0xc5,
0x1d, 0x1c, 0xb8, 0xe1, 0x1e, 0x7e, 0xa6, 0x0f, 0x0e, 0xf6, 0x30, 0xea, 0x55, 0x0b, 0x7f, 0xcb, 0xb8, 0xa6, 0x0f, 0x1f, 0xff, 0xf2, 0xc9, 0x8d, 0xaf, 0xbc, 0xf4, 0x6a, 0xea, 0x46, 0xc1, 0xde,
0x07, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x6e, 0xdb, 0x6f, 0x5b, 0x69, 0x0b, 0x00, 0x00, 0xc1, 0x81, 0x1b, 0xee, 0xe1, 0xf7, 0xfb, 0xe0, 0x60, 0x0f, 0xbd, 0x5e, 0xb5, 0xf0, 0x7f, 0x7d,
0xf0, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4b, 0xd8, 0x21, 0x5f, 0x9b, 0x0b, 0x00, 0x00,
} }
...@@ -134,7 +134,7 @@ const ( ...@@ -134,7 +134,7 @@ const (
EventAddParaChainBlockDetail = 126 EventAddParaChainBlockDetail = 126
EventGetSeqByHash = 127 EventGetSeqByHash = 127
EventLocalPrefixCount = 128 EventLocalPrefixCount = 128
EventWalletCreateTx = 129 //EventWalletCreateTx = 129
EventStoreList = 130 EventStoreList = 130
EventStoreListReply = 131 EventStoreListReply = 131
EventListBlockSeqCB = 132 EventListBlockSeqCB = 132
...@@ -284,7 +284,7 @@ var eventName = map[int]string{ ...@@ -284,7 +284,7 @@ var eventName = map[int]string{
127: "EventGetSeqByHash", 127: "EventGetSeqByHash",
128: "EventLocalPrefixCount", 128: "EventLocalPrefixCount",
//todo: 这个可能后面会删除 //todo: 这个可能后面会删除
EventWalletCreateTx: "EventWalletCreateTx", //EventWalletCreateTx: "EventWalletCreateTx",
EventStoreList: "EventStoreList", EventStoreList: "EventStoreList",
EventStoreListReply: "EventStoreListReply", EventStoreListReply: "EventStoreListReply",
// Token // Token
......
...@@ -63,6 +63,10 @@ message BlockSeq { ...@@ -63,6 +63,10 @@ message BlockSeq {
BlockDetail detail = 3; BlockDetail detail = 3;
} }
message BlockSeqs {
repeated BlockSeq seqs = 1;
}
//节点ID以及对应的Block //节点ID以及对应的Block
message BlockPid { message BlockPid {
string pid = 1; string pid = 1;
......
...@@ -224,27 +224,6 @@ message Int32 { ...@@ -224,27 +224,6 @@ message Int32 {
int32 data = 1; int32 data = 1;
} }
// 某些交易需要存在一些复杂的算法,所以需要请求服务器协助构建交易,返回对应交易哈希值,后续签名可以根据此哈希值进行处理
message ReqCreateTransaction {
string tokenname = 1;
// 构建交易类型
// 0:普通的交易(暂不支持)
// 1:隐私交易 公开->隐私
// 2:隐私交易 隐私->隐私
// 3:隐私交易 隐私->公开
int32 type = 2;
int64 amount = 3;
string note = 4;
// 普通交易的发送方
string from = 5;
// 普通交易的接收方
string to = 6;
// 隐私交易,接收方的公钥对
string pubkeypair = 10;
int32 mixcount = 11;
int64 expire = 12;
}
message ReqAccountList { message ReqAccountList {
bool withoutBalance = 1; bool withoutBalance = 1;
} }
...@@ -1577,118 +1577,6 @@ func (m *Int32) GetData() int32 { ...@@ -1577,118 +1577,6 @@ func (m *Int32) GetData() int32 {
return 0 return 0
} }
// 某些交易需要存在一些复杂的算法,所以需要请求服务器协助构建交易,返回对应交易哈希值,后续签名可以根据此哈希值进行处理
type ReqCreateTransaction struct {
Tokenname string `protobuf:"bytes,1,opt,name=tokenname,proto3" json:"tokenname,omitempty"`
// 构建交易类型
// 0:普通的交易(暂不支持)
// 1:隐私交易 公开->隐私
// 2:隐私交易 隐私->隐私
// 3:隐私交易 隐私->公开
Type int32 `protobuf:"varint,2,opt,name=type,proto3" json:"type,omitempty"`
Amount int64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"`
Note string `protobuf:"bytes,4,opt,name=note,proto3" json:"note,omitempty"`
// 普通交易的发送方
From string `protobuf:"bytes,5,opt,name=from,proto3" json:"from,omitempty"`
// 普通交易的接收方
To string `protobuf:"bytes,6,opt,name=to,proto3" json:"to,omitempty"`
// 隐私交易,接收方的公钥对
Pubkeypair string `protobuf:"bytes,10,opt,name=pubkeypair,proto3" json:"pubkeypair,omitempty"`
Mixcount int32 `protobuf:"varint,11,opt,name=mixcount,proto3" json:"mixcount,omitempty"`
Expire int64 `protobuf:"varint,12,opt,name=expire,proto3" json:"expire,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReqCreateTransaction) Reset() { *m = ReqCreateTransaction{} }
func (m *ReqCreateTransaction) String() string { return proto.CompactTextString(m) }
func (*ReqCreateTransaction) ProtoMessage() {}
func (*ReqCreateTransaction) Descriptor() ([]byte, []int) {
return fileDescriptor_b88fd140af4deb6f, []int{28}
}
func (m *ReqCreateTransaction) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReqCreateTransaction.Unmarshal(m, b)
}
func (m *ReqCreateTransaction) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReqCreateTransaction.Marshal(b, m, deterministic)
}
func (m *ReqCreateTransaction) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReqCreateTransaction.Merge(m, src)
}
func (m *ReqCreateTransaction) XXX_Size() int {
return xxx_messageInfo_ReqCreateTransaction.Size(m)
}
func (m *ReqCreateTransaction) XXX_DiscardUnknown() {
xxx_messageInfo_ReqCreateTransaction.DiscardUnknown(m)
}
var xxx_messageInfo_ReqCreateTransaction proto.InternalMessageInfo
func (m *ReqCreateTransaction) GetTokenname() string {
if m != nil {
return m.Tokenname
}
return ""
}
func (m *ReqCreateTransaction) GetType() int32 {
if m != nil {
return m.Type
}
return 0
}
func (m *ReqCreateTransaction) GetAmount() int64 {
if m != nil {
return m.Amount
}
return 0
}
func (m *ReqCreateTransaction) GetNote() string {
if m != nil {
return m.Note
}
return ""
}
func (m *ReqCreateTransaction) GetFrom() string {
if m != nil {
return m.From
}
return ""
}
func (m *ReqCreateTransaction) GetTo() string {
if m != nil {
return m.To
}
return ""
}
func (m *ReqCreateTransaction) GetPubkeypair() string {
if m != nil {
return m.Pubkeypair
}
return ""
}
func (m *ReqCreateTransaction) GetMixcount() int32 {
if m != nil {
return m.Mixcount
}
return 0
}
func (m *ReqCreateTransaction) GetExpire() int64 {
if m != nil {
return m.Expire
}
return 0
}
type ReqAccountList struct { type ReqAccountList struct {
WithoutBalance bool `protobuf:"varint,1,opt,name=withoutBalance,proto3" json:"withoutBalance,omitempty"` WithoutBalance bool `protobuf:"varint,1,opt,name=withoutBalance,proto3" json:"withoutBalance,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
...@@ -1700,7 +1588,7 @@ func (m *ReqAccountList) Reset() { *m = ReqAccountList{} } ...@@ -1700,7 +1588,7 @@ func (m *ReqAccountList) Reset() { *m = ReqAccountList{} }
func (m *ReqAccountList) String() string { return proto.CompactTextString(m) } func (m *ReqAccountList) String() string { return proto.CompactTextString(m) }
func (*ReqAccountList) ProtoMessage() {} func (*ReqAccountList) ProtoMessage() {}
func (*ReqAccountList) Descriptor() ([]byte, []int) { func (*ReqAccountList) Descriptor() ([]byte, []int) {
return fileDescriptor_b88fd140af4deb6f, []int{29} return fileDescriptor_b88fd140af4deb6f, []int{28}
} }
func (m *ReqAccountList) XXX_Unmarshal(b []byte) error { func (m *ReqAccountList) XXX_Unmarshal(b []byte) error {
...@@ -1757,93 +1645,88 @@ func init() { ...@@ -1757,93 +1645,88 @@ func init() {
proto.RegisterType((*ReplySignRawTx)(nil), "types.ReplySignRawTx") proto.RegisterType((*ReplySignRawTx)(nil), "types.ReplySignRawTx")
proto.RegisterType((*ReportErrEvent)(nil), "types.ReportErrEvent") proto.RegisterType((*ReportErrEvent)(nil), "types.ReportErrEvent")
proto.RegisterType((*Int32)(nil), "types.Int32") proto.RegisterType((*Int32)(nil), "types.Int32")
proto.RegisterType((*ReqCreateTransaction)(nil), "types.ReqCreateTransaction")
proto.RegisterType((*ReqAccountList)(nil), "types.ReqAccountList") proto.RegisterType((*ReqAccountList)(nil), "types.ReqAccountList")
} }
func init() { proto.RegisterFile("wallet.proto", fileDescriptor_b88fd140af4deb6f) } func init() { proto.RegisterFile("wallet.proto", fileDescriptor_b88fd140af4deb6f) }
var fileDescriptor_b88fd140af4deb6f = []byte{ var fileDescriptor_b88fd140af4deb6f = []byte{
// 1292 bytes of a gzipped FileDescriptorProto // 1220 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0x5d, 0x6e, 0x1b, 0xb7, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xdd, 0x6e, 0x1b, 0x37,
0x13, 0xc7, 0x4a, 0x96, 0x6d, 0xd1, 0xb2, 0x93, 0x2c, 0x92, 0x40, 0xf0, 0xff, 0x9f, 0xc4, 0x61, 0x13, 0xc5, 0x4a, 0x96, 0x6d, 0xd1, 0xb2, 0x93, 0x10, 0x49, 0xb0, 0xf0, 0xf7, 0xa5, 0x51, 0x58,
0x91, 0xd4, 0x05, 0x0a, 0x07, 0x88, 0x5e, 0x8a, 0x02, 0x05, 0xe2, 0x7c, 0x3a, 0x80, 0x93, 0x1a, 0x24, 0x75, 0x81, 0xc2, 0x01, 0xa2, 0x9b, 0xa2, 0x40, 0x81, 0x38, 0xbf, 0x0e, 0xe0, 0xa4, 0x06,
0x94, 0x8a, 0x02, 0x7d, 0x29, 0xa8, 0xdd, 0xb1, 0x44, 0x68, 0xb5, 0x5c, 0x73, 0x29, 0x4b, 0xba, 0xa5, 0xa2, 0x40, 0x6f, 0x0a, 0x7a, 0x77, 0x2c, 0x11, 0x5e, 0x91, 0x6b, 0x2e, 0x65, 0x49, 0x6f,
0x49, 0x0f, 0xd0, 0x23, 0xf4, 0x0c, 0x7d, 0xef, 0x3d, 0x7a, 0x88, 0x62, 0x86, 0xe4, 0x6a, 0x37, 0xd2, 0x07, 0xe8, 0x23, 0xf4, 0x19, 0x7a, 0xdf, 0x37, 0x2a, 0x38, 0x24, 0xb5, 0xbb, 0xa9, 0x7b,
0x71, 0x1f, 0x82, 0xbe, 0xf1, 0x37, 0x1c, 0xce, 0x70, 0x7e, 0xf3, 0x41, 0xb2, 0xde, 0x52, 0x66, 0x51, 0xf4, 0x8e, 0xe7, 0x70, 0x38, 0xc3, 0x39, 0x43, 0x0e, 0x49, 0x06, 0x4b, 0x51, 0x14, 0x60,
0x19, 0xd8, 0x93, 0xc2, 0x68, 0xab, 0xe3, 0x8e, 0x5d, 0x17, 0x50, 0x1e, 0xde, 0xb1, 0x46, 0xe6, 0x8f, 0x4b, 0xa3, 0xad, 0xa6, 0x3d, 0xbb, 0x2e, 0xa1, 0x3a, 0xbc, 0x67, 0x8d, 0x50, 0x95, 0xc8,
0xa5, 0x4c, 0xac, 0xd2, 0xb9, 0xdb, 0x39, 0xbc, 0x3d, 0xce, 0x74, 0x32, 0x4b, 0xa6, 0x52, 0x05, 0xac, 0xd4, 0xca, 0xcf, 0x1c, 0xde, 0xbd, 0x28, 0x74, 0x76, 0x95, 0xcd, 0x84, 0x8c, 0xcc, 0xbe,
0xc9, 0xbe, 0x4c, 0x12, 0xbd, 0xc8, 0xfd, 0xd1, 0xc3, 0x03, 0x58, 0x41, 0xb2, 0xb0, 0xda, 0x38, 0xc8, 0x32, 0xbd, 0x50, 0x61, 0xe9, 0xe1, 0x01, 0xac, 0x20, 0x5b, 0x58, 0x6d, 0x3c, 0x66, 0xbf,
0xcc, 0xff, 0x68, 0xb1, 0x83, 0x9f, 0xc9, 0xf6, 0x68, 0xf5, 0x1a, 0xac, 0x54, 0x59, 0xcc, 0x59, 0x77, 0xc8, 0xc1, 0x4f, 0xe8, 0x7b, 0xb2, 0x7a, 0x03, 0x56, 0xc8, 0x82, 0x32, 0xd2, 0xb1, 0xab,
0xcb, 0xae, 0xfa, 0xd1, 0x51, 0x74, 0xbc, 0xf7, 0x3c, 0x3e, 0x21, 0x57, 0x27, 0xa3, 0x8d, 0x27, 0x34, 0x19, 0x26, 0x47, 0x7b, 0x2f, 0xe8, 0x31, 0x86, 0x3a, 0x9e, 0xd4, 0x91, 0x78, 0xc7, 0xae,
0xd1, 0xb2, 0xab, 0xf8, 0x5b, 0xb6, 0x63, 0x20, 0x01, 0x55, 0xd8, 0x7e, 0xab, 0xa1, 0x28, 0x9c, 0xe8, 0x37, 0x64, 0xc7, 0x40, 0x06, 0xb2, 0xb4, 0x69, 0xa7, 0x65, 0xc8, 0x3d, 0xfb, 0x46, 0x58,
0xf4, 0xb5, 0xb4, 0x52, 0x04, 0x95, 0xf8, 0x3e, 0xdb, 0x9e, 0x82, 0x9a, 0x4c, 0x6d, 0xbf, 0x7d, 0xc1, 0xa3, 0x09, 0x7d, 0x48, 0xb6, 0x67, 0x20, 0xa7, 0x33, 0x9b, 0x76, 0x87, 0xc9, 0x51, 0x97,
0x14, 0x1d, 0xb7, 0x85, 0x47, 0xf1, 0x5d, 0xd6, 0x51, 0x79, 0x0a, 0xab, 0xfe, 0x16, 0x89, 0x1d, 0x07, 0x44, 0xef, 0x93, 0x9e, 0x54, 0x39, 0xac, 0xd2, 0x2d, 0xa4, 0x3d, 0xa0, 0xff, 0x27, 0x7d,
0x88, 0xff, 0xcf, 0xba, 0x14, 0x85, 0x55, 0x73, 0xe8, 0x77, 0x68, 0x67, 0x23, 0x40, 0x5b, 0x72, 0xcc, 0xc2, 0xca, 0x39, 0xa4, 0x3d, 0x9c, 0xa9, 0x09, 0xe7, 0x4b, 0xcc, 0x5d, 0x42, 0xe9, 0xb6,
0x8e, 0x01, 0xf5, 0xb7, 0x9d, 0x2d, 0x87, 0xe2, 0x43, 0xb6, 0x7b, 0x69, 0xf4, 0x5c, 0xa6, 0xa9, 0xf7, 0xe5, 0x11, 0x3d, 0x24, 0xbb, 0x97, 0x46, 0xcf, 0x45, 0x9e, 0x9b, 0x74, 0x67, 0x98, 0x1c,
0xe9, 0xef, 0x1c, 0x45, 0xc7, 0x5d, 0x51, 0x61, 0x3c, 0x63, 0x57, 0x53, 0x59, 0x4e, 0xfb, 0xbb, 0xf5, 0xf9, 0x06, 0xbb, 0x35, 0x76, 0x35, 0x13, 0xd5, 0x2c, 0xdd, 0x1d, 0x26, 0x47, 0x03, 0x1e,
0x47, 0xd1, 0x71, 0x4f, 0x78, 0x14, 0x3f, 0x64, 0xcc, 0xc5, 0xf4, 0x51, 0xce, 0xa1, 0xdf, 0xa5, 0x10, 0xfd, 0x82, 0x10, 0x9f, 0xd3, 0x27, 0x31, 0x87, 0xb4, 0x8f, 0xab, 0x1a, 0x0c, 0x4d, 0xc9,
0x53, 0x35, 0x49, 0xdc, 0x67, 0x3b, 0x85, 0x5c, 0x67, 0x5a, 0xa6, 0x7d, 0x46, 0x07, 0x03, 0xe4, 0x4e, 0x29, 0xd6, 0x85, 0x16, 0x79, 0x4a, 0x70, 0x61, 0x84, 0xec, 0x1d, 0xb9, 0xd3, 0x56, 0xad,
0x6f, 0xd9, 0xad, 0x26, 0x6b, 0x65, 0x3c, 0x60, 0x5d, 0x1b, 0x40, 0x3f, 0x3a, 0x6a, 0x1f, 0xef, 0xa2, 0x23, 0xd2, 0xb7, 0x11, 0xa4, 0xc9, 0xb0, 0x7b, 0xb4, 0xf7, 0xe2, 0x41, 0x10, 0xa5, 0x6d,
0x3d, 0xbf, 0xe7, 0x49, 0x69, 0xaa, 0x8a, 0x8d, 0x1e, 0xbf, 0x66, 0xb1, 0xdb, 0x3c, 0x75, 0x59, 0xca, 0x6b, 0x3b, 0x76, 0x43, 0xa8, 0x9f, 0x3c, 0xf1, 0x55, 0x1a, 0x5b, 0x6d, 0x7c, 0x5c, 0x23,
0x1a, 0x5a, 0x6d, 0x9c, 0x5f, 0xa3, 0xae, 0x67, 0xb0, 0xa6, 0x34, 0x74, 0x45, 0x80, 0xc8, 0x58, 0x6f, 0xae, 0x60, 0x8d, 0x65, 0xe8, 0xf3, 0x08, 0x9d, 0x62, 0x85, 0xb8, 0x80, 0x02, 0x55, 0xef,
0x26, 0xc7, 0x90, 0x11, 0xeb, 0x5d, 0xe1, 0x40, 0x1c, 0xb3, 0x2d, 0x8a, 0xbb, 0x4d, 0x42, 0x5a, 0x73, 0x0f, 0x28, 0x25, 0x5b, 0x98, 0x77, 0x17, 0x49, 0x1c, 0x3b, 0x15, 0x9d, 0x5e, 0x63, 0x2b,
0x23, 0x8b, 0xc8, 0xd7, 0xd0, 0xca, 0x79, 0x41, 0xfc, 0x76, 0xc5, 0x46, 0xc0, 0x5f, 0xb0, 0x9e, 0xe6, 0x25, 0xea, 0xdb, 0xe7, 0x35, 0xc1, 0x5e, 0x92, 0x81, 0x8f, 0x7b, 0xbe, 0x3c, 0x75, 0x4a,
0xf3, 0x7b, 0xb1, 0x3c, 0x43, 0x26, 0xee, 0xb3, 0xed, 0x82, 0x56, 0xe4, 0xb0, 0x27, 0x3c, 0xc2, 0x3c, 0x24, 0xdb, 0x25, 0x8e, 0x30, 0xe0, 0x80, 0x07, 0xe4, 0x76, 0x62, 0x84, 0xca, 0x2b, 0x6b,
0x9b, 0x18, 0x99, 0xa7, 0xa5, 0x35, 0xde, 0x63, 0x80, 0xfc, 0xb7, 0x28, 0x98, 0x18, 0x5a, 0x69, 0x42, 0xc4, 0x08, 0xd9, 0xaf, 0x49, 0x74, 0x31, 0xb6, 0xc2, 0x2e, 0x2a, 0xca, 0xc8, 0x40, 0x56,
0x17, 0x65, 0xcc, 0x59, 0x4f, 0x95, 0x4e, 0x72, 0xae, 0x93, 0x19, 0x19, 0xda, 0x15, 0x0d, 0x99, 0x9e, 0x39, 0xd3, 0xd9, 0x15, 0x3a, 0xda, 0xe5, 0x2d, 0xce, 0xdb, 0x9c, 0x2c, 0xac, 0xfe, 0x28,
0xd3, 0x39, 0x5d, 0x58, 0xfd, 0x41, 0xe5, 0x2a, 0x9f, 0x90, 0x4d, 0xd2, 0xd9, 0xc8, 0xf0, 0xe2, 0x95, 0x54, 0x53, 0xf4, 0x89, 0x36, 0x35, 0xe7, 0x36, 0x2e, 0xab, 0x53, 0x51, 0x8d, 0x01, 0x72,
0xaa, 0x3c, 0x93, 0xe5, 0x10, 0x20, 0xa5, 0x88, 0x76, 0xc5, 0x46, 0xe0, 0x2c, 0x8c, 0x54, 0x32, 0xcc, 0x68, 0x97, 0xd7, 0x84, 0xf7, 0x30, 0x91, 0xd9, 0x55, 0x88, 0xb2, 0x15, 0x3d, 0xd4, 0x1c,
0xf3, 0x5e, 0xb6, 0x82, 0x85, 0x8d, 0x8c, 0xbf, 0x08, 0x25, 0xed, 0x49, 0x2d, 0xe3, 0x13, 0xb6, 0x7b, 0x19, 0x8f, 0x74, 0x10, 0xb5, 0xa2, 0xc7, 0x64, 0xc7, 0x5f, 0xa0, 0x58, 0x99, 0xfb, 0xad,
0xe3, 0x1a, 0x28, 0x64, 0xe6, 0x6e, 0x23, 0x33, 0x5e, 0x4f, 0x04, 0x25, 0xfe, 0x8e, 0xed, 0x37, 0xca, 0x04, 0x3b, 0x1e, 0x8d, 0xd8, 0x7b, 0xb2, 0xdf, 0x9a, 0xa1, 0x43, 0xd2, 0x15, 0x59, 0x16,
0x76, 0xe2, 0x23, 0xd6, 0x96, 0x49, 0xe2, 0x9b, 0xe2, 0xc0, 0x1f, 0x0e, 0xc7, 0x70, 0xeb, 0xe6, 0x2e, 0xc5, 0x41, 0x58, 0x1c, 0x97, 0xb9, 0xa9, 0xdb, 0x2b, 0xc3, 0x66, 0x51, 0xa4, 0x1f, 0x15,
0xcc, 0xf0, 0x69, 0x20, 0xe9, 0xa7, 0x9c, 0x08, 0x40, 0x9e, 0x65, 0x59, 0x2e, 0x53, 0x9f, 0x58, 0x0a, 0xe0, 0x74, 0x16, 0x55, 0xb5, 0xcc, 0x43, 0x61, 0x03, 0x72, 0x3a, 0xbb, 0xe2, 0xe8, 0x85,
0x8f, 0x90, 0x67, 0x4c, 0x8e, 0x5e, 0xb8, 0x7e, 0x6a, 0x8b, 0x00, 0xe3, 0xa7, 0xec, 0xc0, 0xdd, 0xbf, 0x4f, 0x5d, 0x1e, 0x21, 0x7d, 0x46, 0x0e, 0xfc, 0xae, 0x7e, 0x30, 0x3e, 0xc5, 0xa0, 0xc9,
0xea, 0x47, 0xe3, 0x42, 0xf4, 0x9c, 0x7c, 0x22, 0xe5, 0x8f, 0xd9, 0xde, 0x3b, 0xc8, 0x91, 0xa3, 0x67, 0x2c, 0x7b, 0x42, 0xf6, 0xde, 0x83, 0x72, 0x1a, 0x9d, 0x09, 0x35, 0x75, 0x47, 0xa2, 0x10,
0x73, 0x99, 0x4f, 0xb0, 0x24, 0x32, 0x99, 0x4f, 0xc8, 0x4d, 0x47, 0xd0, 0x9a, 0x3f, 0x41, 0x15, 0x6a, 0x8a, 0x61, 0x7a, 0x1c, 0xc7, 0xec, 0xa9, 0x33, 0xb1, 0xce, 0xe4, 0xd5, 0xfa, 0x7c, 0xf9,
0x8b, 0x2a, 0x2f, 0xd7, 0x17, 0xcb, 0x7f, 0xbb, 0x0b, 0xff, 0x9e, 0xf5, 0x86, 0xf2, 0x1a, 0x2a, 0x4f, 0x7b, 0x61, 0xdf, 0x91, 0xc1, 0x58, 0xdc, 0xc0, 0xc6, 0x8e, 0x92, 0xad, 0xca, 0xd5, 0xc2,
0xbd, 0x98, 0x6d, 0x95, 0x98, 0x0b, 0xa7, 0x45, 0xeb, 0xda, 0xd9, 0x56, 0xe3, 0xec, 0x23, 0xd6, 0x5b, 0xe1, 0xb8, 0xb1, 0xb6, 0xd3, 0x5a, 0xfb, 0x98, 0xf4, 0x39, 0x94, 0xc5, 0x1a, 0x6b, 0x75,
0x15, 0x50, 0x64, 0x6b, 0xca, 0xd5, 0x0d, 0x07, 0xf9, 0x19, 0x8b, 0x05, 0x5c, 0xf9, 0xc2, 0x01, 0xcb, 0x42, 0x76, 0x4a, 0x28, 0x87, 0xeb, 0x70, 0x70, 0xc0, 0x9e, 0x6f, 0xd2, 0xd7, 0x45, 0xee,
0x7b, 0x51, 0x85, 0xaf, 0xb3, 0x14, 0x41, 0x28, 0x78, 0x0f, 0x71, 0x27, 0x87, 0x25, 0xed, 0xf8, 0x40, 0x3c, 0xf0, 0x01, 0xba, 0x19, 0x05, 0x4b, 0x9c, 0x09, 0x07, 0x30, 0x40, 0xf6, 0x94, 0xec,
0x02, 0xf4, 0x90, 0x3f, 0x61, 0xfb, 0x02, 0xae, 0x3e, 0xc2, 0x32, 0xe4, 0xa8, 0xca, 0x40, 0x54, 0x73, 0xb8, 0xfe, 0x04, 0xcb, 0x58, 0xa3, 0x4d, 0x05, 0x92, 0x66, 0x05, 0x2e, 0x49, 0xba, 0x09,
0xcf, 0xc0, 0x25, 0xeb, 0x57, 0x0e, 0x6b, 0x53, 0xec, 0x5c, 0x95, 0x34, 0x97, 0x70, 0x46, 0x8c, 0xd8, 0xe8, 0x62, 0x67, 0xb2, 0xc2, 0xbe, 0xe4, 0x7a, 0xc4, 0x64, 0x15, 0x4f, 0xbd, 0x47, 0xce,
0x56, 0xa1, 0xea, 0x1d, 0x42, 0x4b, 0x64, 0x92, 0x5c, 0x76, 0x84, 0x03, 0x58, 0x98, 0xa9, 0x32, 0x13, 0xba, 0xc4, 0x90, 0x3d, 0xee, 0x81, 0x3b, 0x98, 0xb9, 0x34, 0x80, 0xcb, 0xb1, 0x08, 0x3d,
0x40, 0xc7, 0x29, 0x09, 0x1d, 0xb1, 0x11, 0xf0, 0x33, 0x76, 0xbf, 0xf2, 0xf3, 0x7e, 0x5e, 0x68, 0x5e, 0x13, 0xec, 0x94, 0x3c, 0xdc, 0xc4, 0xf9, 0x30, 0x2f, 0xb5, 0xb1, 0xe7, 0xe1, 0xce, 0xfe,
0x63, 0x2f, 0x7c, 0xcf, 0x7e, 0x61, 0x37, 0xf3, 0xdf, 0xa3, 0x9a, 0xa9, 0x21, 0xe4, 0xe9, 0x48, 0xcb, 0xdb, 0xcc, 0x7e, 0x4b, 0x1a, 0xae, 0xc6, 0xa0, 0xf2, 0x89, 0x3e, 0xc9, 0x73, 0x03, 0x55,
0x9f, 0xa6, 0xa9, 0x81, 0xb2, 0x44, 0x46, 0xf1, 0x8a, 0x81, 0x51, 0x5c, 0xc7, 0x07, 0xac, 0x65, 0xe5, 0x14, 0x75, 0x5b, 0x8c, 0x8a, 0xba, 0x31, 0x3d, 0x20, 0x1d, 0xab, 0x83, 0x87, 0x8e, 0xd5,
0xb5, 0xb7, 0xd0, 0xb2, 0xba, 0x36, 0x20, 0xdb, 0x8d, 0x01, 0x19, 0xb3, 0xad, 0x5c, 0x5b, 0xf0, 0x8d, 0x06, 0xd9, 0x6d, 0x35, 0x48, 0x4a, 0xb6, 0x94, 0xb6, 0x10, 0x7a, 0x01, 0x8e, 0xdd, 0xd6,
0xb3, 0x80, 0xd6, 0x78, 0x35, 0x55, 0x8e, 0xf4, 0x0c, 0x72, 0x1a, 0xb4, 0xbb, 0x22, 0xc0, 0xf8, 0x64, 0x35, 0xd1, 0x57, 0xa0, 0xb0, 0xd1, 0xee, 0xf2, 0x08, 0xe9, 0x90, 0xec, 0x59, 0x37, 0x18,
0x88, 0xed, 0x59, 0x5c, 0x0c, 0xd7, 0xf3, 0xb1, 0xce, 0x68, 0xd6, 0x76, 0x45, 0x5d, 0xc4, 0xbf, 0xaf, 0xe7, 0x17, 0xba, 0xc0, 0x5e, 0xdb, 0xe7, 0x4d, 0x8a, 0x7d, 0x4d, 0xee, 0x34, 0x2b, 0xf9,
0x61, 0xb7, 0xea, 0x99, 0x7c, 0x0b, 0xf5, 0xd9, 0x1c, 0xd5, 0x5d, 0xf3, 0x1f, 0xd8, 0x9d, 0xba, 0x0e, 0x9a, 0xbd, 0x39, 0x69, 0x86, 0x66, 0xdf, 0x93, 0x7b, 0x4d, 0xd3, 0xb3, 0x56, 0xd3, 0x4a,
0xea, 0x79, 0x63, 0x68, 0x45, 0xb5, 0xa1, 0x75, 0x33, 0x21, 0x5f, 0xb3, 0x7b, 0xd5, 0xf1, 0x0f, 0x1a, 0x4d, 0xeb, 0x76, 0x41, 0xbe, 0x22, 0x0f, 0x36, 0xcb, 0x3f, 0x82, 0x99, 0xc2, 0x2b, 0x51,
0x60, 0x26, 0xf0, 0x52, 0x66, 0x32, 0x4f, 0xc0, 0x87, 0x1e, 0x85, 0xd0, 0xf9, 0x5f, 0x11, 0x39, 0x08, 0x95, 0x41, 0x48, 0x3d, 0x89, 0xa9, 0xb3, 0x3f, 0x13, 0x0c, 0x84, 0x19, 0x9c, 0x1b, 0x78,
0xa2, 0x08, 0x2e, 0x0c, 0xbc, 0x32, 0x20, 0x2d, 0xc4, 0x8f, 0x59, 0x2f, 0xc1, 0x95, 0x36, 0xbf, 0x6d, 0x40, 0x58, 0xa0, 0x4f, 0xc8, 0x20, 0x73, 0x23, 0x6d, 0x7e, 0x69, 0x04, 0xdc, 0x0b, 0x9c,
0xd6, 0x1c, 0xee, 0x79, 0x19, 0x52, 0x4b, 0xdc, 0xe0, 0x13, 0xd0, 0xf2, 0xdc, 0x48, 0xf7, 0xd0, 0x93, 0x16, 0xb5, 0x71, 0x4f, 0x40, 0x27, 0x68, 0x23, 0xfc, 0x43, 0x53, 0xf9, 0xe4, 0x7d, 0x5b,
0x94, 0x2e, 0x78, 0x37, 0x56, 0x3d, 0xa2, 0x09, 0x94, 0x5b, 0xa3, 0xd3, 0x85, 0xab, 0x04, 0xc7, 0x0d, 0x08, 0x3b, 0x90, 0xb2, 0x46, 0xe7, 0x0b, 0x7f, 0x12, 0xbc, 0x9e, 0x2d, 0x8e, 0x3e, 0x22,
0x67, 0x43, 0x16, 0x3f, 0x60, 0x4c, 0x2f, 0x73, 0xf0, 0x0e, 0x3b, 0x6e, 0xfa, 0x92, 0xe4, 0xd4, 0x44, 0x2f, 0x15, 0x84, 0x80, 0x3d, 0xdf, 0x7d, 0x91, 0x39, 0x09, 0x69, 0x5a, 0x6d, 0x45, 0x11,
0x87, 0x69, 0xb5, 0x95, 0x99, 0x7f, 0xc2, 0x1c, 0x40, 0x69, 0x61, 0x54, 0x02, 0xf4, 0x7c, 0xb5, 0x9e, 0x30, 0x0f, 0x1c, 0x5b, 0x1a, 0x99, 0x01, 0x3e, 0x5f, 0x5d, 0xee, 0x01, 0x33, 0xe4, 0x7e,
0x85, 0x03, 0xdc, 0xb0, 0xbb, 0x21, 0xa4, 0xb7, 0x2a, 0x57, 0xe5, 0xd4, 0x47, 0xf5, 0x15, 0xdb, 0x4c, 0xe9, 0x9d, 0x54, 0xb2, 0x9a, 0x85, 0xac, 0xbe, 0x24, 0xfb, 0x97, 0x88, 0xa1, 0x95, 0xd6,
0xbf, 0x24, 0x0c, 0x8d, 0xb0, 0x7a, 0x41, 0x78, 0xea, 0x1f, 0x3e, 0x1f, 0x43, 0xab, 0x11, 0x43, 0x20, 0x92, 0x27, 0xe1, 0xe1, 0x0b, 0x39, 0x74, 0x5a, 0x39, 0xb4, 0xf7, 0xd7, 0xfd, 0x6c, 0x7f,
0xf3, 0x7e, 0xed, 0x4f, 0xee, 0xc7, 0x8b, 0x8d, 0x4f, 0x01, 0xd7, 0x7a, 0x56, 0x63, 0xd2, 0x10, 0xac, 0xac, 0x63, 0x72, 0xb8, 0xd1, 0x57, 0x0d, 0x25, 0x0d, 0xe2, 0xb6, 0x92, 0x81, 0xfb, 0x2f,
0x6e, 0x32, 0xe9, 0x65, 0xff, 0xc5, 0x23, 0x50, 0x31, 0x7d, 0xd0, 0xa9, 0xba, 0x5c, 0xbf, 0xd2, 0x11, 0x01, 0x0f, 0xd3, 0x47, 0x9d, 0xcb, 0xcb, 0xf5, 0x6b, 0xad, 0x2e, 0xe5, 0x94, 0xde, 0x25,
0xf9, 0xa5, 0x9a, 0xc4, 0xb7, 0x59, 0x7b, 0xd3, 0x32, 0xb8, 0xc4, 0x74, 0xeb, 0x22, 0x54, 0xba, 0xdd, 0xfa, 0xca, 0xb8, 0xa1, 0x2b, 0xb7, 0x2e, 0xe3, 0x49, 0xd7, 0xa5, 0x13, 0xec, 0x46, 0x14,
0x2e, 0x90, 0xb0, 0x6b, 0x99, 0x2d, 0xc0, 0x9b, 0x73, 0x00, 0x3f, 0x02, 0x73, 0xb4, 0xa3, 0xc0, 0x0b, 0x08, 0xee, 0x3c, 0x70, 0x1f, 0x81, 0xb9, 0xf3, 0x23, 0xc1, 0x84, 0xda, 0x6c, 0x30, 0xfb,
0xf8, 0xdc, 0x54, 0x98, 0xff, 0x19, 0xb1, 0x9e, 0x80, 0xab, 0xa1, 0x9a, 0xe4, 0x42, 0x2e, 0x47, 0x23, 0x21, 0x03, 0x0e, 0xd7, 0x63, 0x39, 0x55, 0x5c, 0x2c, 0x27, 0xab, 0x5b, 0x0f, 0x61, 0xe3,
0xab, 0x1b, 0x8b, 0xb0, 0xd6, 0xaf, 0xad, 0xcf, 0xfa, 0xd5, 0xae, 0xce, 0x60, 0x15, 0x1c, 0x12, 0xbe, 0x76, 0xfe, 0x76, 0x5f, 0xed, 0xea, 0x14, 0x56, 0x31, 0x20, 0x02, 0x97, 0x32, 0xac, 0x4a,
0xc0, 0x90, 0x61, 0x55, 0x28, 0x13, 0x5a, 0xcb, 0xa3, 0xcd, 0xef, 0xa6, 0xe3, 0xa6, 0x88, 0xfb, 0x69, 0xe2, 0xd5, 0x0a, 0xa8, 0xfe, 0xdd, 0xf4, 0x7c, 0x17, 0xf1, 0xbf, 0x1b, 0xac, 0xbd, 0xbb,
0xdd, 0x50, 0xee, 0xb1, 0xe1, 0x76, 0xbc, 0x0d, 0x6a, 0xb7, 0xdb, 0xac, 0x7d, 0x09, 0x40, 0xdf, 0x70, 0x3b, 0xc1, 0x07, 0x5e, 0xb7, 0xbb, 0xa4, 0x7b, 0x09, 0x80, 0xdf, 0x93, 0x2e, 0x77, 0x43,
0x93, 0xb6, 0xc0, 0x25, 0x4e, 0x9b, 0x1c, 0x96, 0xae, 0xf5, 0xe9, 0xf7, 0xd1, 0x15, 0x1b, 0x01, 0xd7, 0x6d, 0x14, 0x2c, 0xfd, 0xd5, 0xc7, 0xdf, 0x47, 0x9f, 0xd7, 0x04, 0x7b, 0x46, 0x0e, 0x7c,
0x7f, 0xca, 0x0e, 0xdc, 0x9c, 0xad, 0x22, 0xa9, 0xee, 0x16, 0xd5, 0xee, 0xc6, 0xc7, 0xa4, 0xa7, 0x9f, 0xdd, 0x64, 0xb2, 0xd9, 0x5b, 0xd2, 0xd8, 0x1b, 0xbb, 0x40, 0x3b, 0x6d, 0xec, 0x5b, 0x63,
0x8d, 0x7d, 0x63, 0xcc, 0x9b, 0x6b, 0xc8, 0x2d, 0xfe, 0x79, 0x70, 0x6c, 0xcc, 0x75, 0xba, 0xc8, 0xde, 0xde, 0x80, 0xb2, 0xee, 0xcf, 0xe3, 0xda, 0xc6, 0x5c, 0xe7, 0x8b, 0x02, 0x82, 0x71, 0x83,
0xc0, 0x2b, 0xd7, 0x24, 0x48, 0x9f, 0xd5, 0x7e, 0xd7, 0x85, 0x5f, 0x61, 0xf4, 0x01, 0xc6, 0xe8, 0x71, 0xf2, 0x59, 0x1d, 0x66, 0x7d, 0xfa, 0x1b, 0xec, 0x62, 0x80, 0x31, 0x3a, 0xd6, 0xcf, 0x03,
0x90, 0x3f, 0x07, 0xf8, 0xff, 0x58, 0xe7, 0x7d, 0x6e, 0x07, 0xcf, 0x91, 0xcc, 0x54, 0x5a, 0x19, 0xf6, 0x3f, 0xd2, 0xfb, 0xa0, 0xec, 0xe8, 0x85, 0x13, 0x33, 0x17, 0x56, 0xc4, 0x37, 0xc7, 0x8d,
0xde, 0x1c, 0x5c, 0xf3, 0xbf, 0x23, 0xaa, 0x25, 0x57, 0x40, 0xb5, 0xf9, 0x4b, 0xff, 0x13, 0x0c, 0xd9, 0xb7, 0x6e, 0x03, 0xd7, 0xa1, 0x45, 0x63, 0xd3, 0x75, 0x0f, 0x9a, 0xb4, 0x33, 0xbd, 0xb0,
0x9d, 0xfa, 0x2e, 0xf2, 0xff, 0x93, 0x20, 0x40, 0x53, 0xf8, 0xc6, 0xfa, 0x01, 0x4c, 0xeb, 0x2f, 0xe1, 0x1a, 0x87, 0x9f, 0xc2, 0x67, 0xec, 0xab, 0xc7, 0x3f, 0x3f, 0x9a, 0x4a, 0x3b, 0x5b, 0x5c,
0x1a, 0x6c, 0x61, 0x50, 0x76, 0x3e, 0x1b, 0x94, 0xdb, 0xd5, 0xa0, 0x7c, 0xc8, 0x58, 0xb1, 0x18, 0x1c, 0x67, 0x7a, 0xfe, 0x7c, 0x34, 0xca, 0xd4, 0x73, 0xfc, 0xd7, 0x8e, 0x46, 0xcf, 0xf1, 0xf9,
0xcf, 0x60, 0x5d, 0x48, 0x15, 0x28, 0xae, 0x49, 0xa8, 0x90, 0xd4, 0xca, 0x3d, 0x04, 0x7b, 0x74, 0xbd, 0xd8, 0xc6, 0x1f, 0xec, 0xe8, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc6, 0x0b, 0xbb, 0xf5,
0x8f, 0x0a, 0xd7, 0x72, 0xde, 0x73, 0x77, 0x71, 0x88, 0x7f, 0x87, 0x7c, 0x5f, 0xf9, 0x17, 0x89, 0x1c, 0x0b, 0x00, 0x00,
0xde, 0x18, 0x7c, 0xbf, 0x95, 0x9d, 0xea, 0x85, 0xf5, 0x53, 0xcb, 0x7f, 0x8c, 0x3e, 0x91, 0xbe,
0x7c, 0xf4, 0xcb, 0x83, 0x89, 0xb2, 0xd3, 0xc5, 0xf8, 0x24, 0xd1, 0xf3, 0x67, 0x83, 0x41, 0x92,
0x3f, 0xa3, 0x6f, 0xfc, 0x60, 0xf0, 0x8c, 0x7e, 0x1b, 0xe3, 0x6d, 0xfa, 0xb0, 0x0f, 0xfe, 0x09,
0x00, 0x00, 0xff, 0xff, 0x9c, 0xe0, 0x98, 0x89, 0x0b, 0x0c, 0x00, 0x00,
} }
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