Commit 8caed19d authored by 张振华's avatar 张振华

merge master

parents c3ea0e84 f78f3e57
......@@ -7,12 +7,11 @@ package para
import (
"github.com/stretchr/testify/assert"
//"github.com/stretchr/testify/mock"
"errors"
"math/rand"
"testing"
"time"
"errors"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/types"
typesmocks "github.com/33cn/chain33/types/mocks"
......
......@@ -11,6 +11,7 @@ import (
"github.com/33cn/chain33/client/mocks"
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/rpc/grpcclient"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/util"
ptypes "github.com/33cn/plugin/plugin/dapp/js/types"
......@@ -30,6 +31,9 @@ func initExec(ldb db.DB, kvdb db.KVDB, code string, t assert.TestingT) *js {
mockapi := &mocks.QueueProtocolAPI{}
mockapi.On("Query", "ticket", "RandNumHash", mock.Anything).Return(&types.ReplyHash{Hash: []byte("hello")}, nil)
e.SetAPI(mockapi)
gclient, err := grpcclient.NewMainChainClient("")
assert.Nil(t, err)
e.SetExecutorAPI(mockapi, gclient)
e.SetLocalDB(kvdb)
e.SetStateDB(kvdb)
c, tx := createCodeTx("test", code)
......
......@@ -392,10 +392,7 @@ func sendAddPublisher(t *testing.T, jrpcClient *jsonclient.JSONClient, mocker *t
}
func sendPublishEvent(t *testing.T, jrpcClient *jsonclient.JSONClient, mocker *testnode.Chain33Mock) (eventID string) {
timeString := "2019-01-21 15:30:00"
layout := "2006-01-02 15:04:05"
ti, err := time.Parse(layout, timeString)
assert.Nil(t, err)
ti := time.Now().AddDate(0, 0, 1)
//1. 调用createrawtransaction 创建交易
req := &rpctypes.CreateTxIn{
Execer: oty.OracleX,
......@@ -403,7 +400,7 @@ func sendPublishEvent(t *testing.T, jrpcClient *jsonclient.JSONClient, mocker *t
Payload: []byte(fmt.Sprintf("{\"type\":\"football\",\"subType\":\"Premier League\",\"time\":%d, \"content\":\"{\\\"team%d\\\":\\\"ChelSea\\\", \\\"team%d\\\":\\\"Manchester\\\",\\\"resultType\\\":\\\"score\\\"}\", \"introduction\":\"guess the sore result of football game between ChelSea and Manchester in 2019-01-21 14:00:00\"}", ti.Unix(), r.Int()%10, r.Int()%10)),
}
var res string
err = jrpcClient.Call("Chain33.CreateTransaction", req, &res)
err := jrpcClient.Call("Chain33.CreateTransaction", req, &res)
assert.Nil(t, err)
gen := mocker.GetHotKey()
tx := getTx(t, res)
......
......@@ -19,6 +19,7 @@ import (
cty "github.com/33cn/chain33/system/dapp/coins/types"
"github.com/33cn/chain33/types"
tokenty "github.com/33cn/plugin/plugin/dapp/token/types"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
)
......@@ -382,3 +383,38 @@ func getprivkey(key string) crypto.PrivKey {
}
return priv
}
func TestToken_validSymbolWithHeight(t *testing.T) {
types.SetTitleOnlyForTest("chain33")
forkBadTokenSymbol := types.GetDappFork(tokenty.TokenX, "ForkBadTokenSymbol")
forkTokenSymbolWithNumber := types.GetDappFork(tokenty.TokenX, "ForkTokenSymbolWithNumber")
t.Log("x", "1", forkBadTokenSymbol, "2", forkTokenSymbolWithNumber)
assert.Equal(t, true, (forkTokenSymbolWithNumber >= forkBadTokenSymbol))
cases := []struct {
symbol []byte
height int64
expect bool
}{
{[]byte("x"), int64(forkBadTokenSymbol - 1), false},
{[]byte("X林"), int64(forkBadTokenSymbol - 1), true},
{[]byte("x"), int64(forkBadTokenSymbol), false},
{[]byte("X林"), int64(forkBadTokenSymbol), false},
{[]byte("x"), int64(forkTokenSymbolWithNumber - 1), false},
{[]byte("X林"), int64(forkTokenSymbolWithNumber - 1), false},
{[]byte("X1"), int64(forkTokenSymbolWithNumber - 1), false},
{[]byte("x"), int64(forkTokenSymbolWithNumber), false},
{[]byte("X林"), int64(forkTokenSymbolWithNumber), false},
{[]byte("X1"), int64(forkTokenSymbolWithNumber), true},
}
for _, c := range cases {
c := c
t.Run("validSymbol", func(t *testing.T) {
assert.Equal(t, c.expect, validSymbolWithHeight(c.symbol, c.height))
})
}
}
......@@ -424,7 +424,11 @@ func isUpperChar(a byte) bool {
return res
}
func validSymbol(cs []byte) bool {
func isDigit(a byte) bool {
return (a <= '9' && a >= '0')
}
func validSymbolForkBadTokenSymbol(cs []byte) bool {
for _, c := range cs {
if !isUpperChar(c) {
return false
......@@ -433,11 +437,27 @@ func validSymbol(cs []byte) bool {
return true
}
func validSymbolForkTokenSymbolWithNumber(cs []byte) bool {
for _, c := range cs {
if !isUpperChar(c) && !isDigit(c) {
return false
}
}
return true
}
func validSymbolOriginal(cs []byte) bool {
symbol := string(cs)
upSymbol := strings.ToUpper(symbol)
return upSymbol == symbol
}
func validSymbolWithHeight(cs []byte, height int64) bool {
if !types.IsDappFork(height, pty.TokenX, "ForkBadTokenSymbol") {
symbol := string(cs)
upSymbol := strings.ToUpper(symbol)
return upSymbol == symbol
if types.IsDappFork(height, pty.TokenX, "ForkTokenSymbolWithNumber") {
return validSymbolForkTokenSymbolWithNumber(cs)
} else if types.IsDappFork(height, pty.TokenX, "ForkBadTokenSymbol") {
return validSymbolForkBadTokenSymbol(cs)
}
return validSymbol(cs)
return validSymbolOriginal(cs)
}
......@@ -22,6 +22,7 @@ func init() {
types.RegisterDappFork(TokenX, "ForkTokenBlackList", 190000)
types.RegisterDappFork(TokenX, "ForkBadTokenSymbol", 184000)
types.RegisterDappFork(TokenX, "ForkTokenPrice", 560000)
types.RegisterDappFork(TokenX, "ForkTokenSymbolWithNumber", 1500000)
}
// TokenType 执行器基类结构体
......
......@@ -46,9 +46,9 @@ type mainChainAPI struct {
}
//New 新建接口
func New(api client.QueueProtocolAPI, grpcaddr string) ExecutorAPI {
func New(api client.QueueProtocolAPI, grpcClient types.Chain33Client) ExecutorAPI {
if types.IsPara() {
return newParaChainAPI(api, grpcaddr)
return newParaChainAPI(api, grpcClient)
}
return &mainChainAPI{api: api}
}
......@@ -85,19 +85,7 @@ type paraChainAPI struct {
errflag int32
}
func newParaChainAPI(api client.QueueProtocolAPI, grpcaddr string) ExecutorAPI {
paraRemoteGrpcClient := types.Conf("config.consensus.sub.para").GStr("ParaRemoteGrpcClient")
if grpcaddr != "" {
paraRemoteGrpcClient = grpcaddr
}
if paraRemoteGrpcClient == "" {
paraRemoteGrpcClient = "127.0.0.1:8002"
}
conn, err := grpc.Dial(paraRemoteGrpcClient, grpc.WithInsecure())
if err != nil {
panic(err)
}
grpcClient := types.NewChain33Client(conn)
func newParaChainAPI(api client.QueueProtocolAPI, grpcClient types.Chain33Client) ExecutorAPI {
return &paraChainAPI{api: api, grpcClient: grpcClient}
}
......
......@@ -9,6 +9,7 @@ import (
"github.com/33cn/chain33/queue"
qmocks "github.com/33cn/chain33/queue/mocks"
"github.com/33cn/chain33/rpc"
"github.com/33cn/chain33/rpc/grpcclient"
"github.com/33cn/chain33/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
......@@ -16,7 +17,9 @@ import (
func TestAPI(t *testing.T) {
api := new(mocks.QueueProtocolAPI)
eapi := New(api, "")
gapi, err := grpcclient.NewMainChainClient("")
assert.Nil(t, err)
eapi := New(api, gapi)
param := &types.ReqHashes{
Hashes: [][]byte{[]byte("hello")},
}
......@@ -54,13 +57,16 @@ func TestAPI(t *testing.T) {
go server.Listen()
time.Sleep(time.Second)
eapi = New(api, "")
eapi = New(api, gapi)
_, err = eapi.GetBlockByHashes(param)
assert.Equal(t, true, IsGrpcError(err))
assert.Equal(t, false, IsGrpcError(nil))
assert.Equal(t, false, IsGrpcError(errors.New("xxxx")))
assert.Equal(t, true, eapi.IsErr())
eapi = New(api, "127.0.0.1:8003")
gapi2, err := grpcclient.NewMainChainClient("127.0.0.1:8003")
assert.Nil(t, err)
eapi = New(api, gapi2)
detail, err = eapi.GetBlockByHashes(param)
assert.Equal(t, err, nil)
assert.Equal(t, detail, &types.BlockDetails{})
......
......@@ -5,6 +5,7 @@
package common
import (
"fmt"
"testing"
"time"
......@@ -25,12 +26,17 @@ var NtpHosts = []string{
func TestGetRealTime(t *testing.T) {
hosts := NtpHosts
nettime := GetRealTimeRetry(hosts, 10)
now := time.Now()
//get nettime error, ignore
if nettime.IsZero() {
return
}
//nettime 获取和本地时间应该
local := time.Now()
t.Log(nettime.Sub(local))
assert.Equal(t, int(local.Sub(nettime)/time.Second), 0)
nettime2 := GetRealTimeRetry(hosts, 10)
//get nettime error, ignore
delt := time.Since(now)
if nettime2.IsZero() {
return
}
fmt.Println(nettime, nettime2)
assert.Equal(t, nettime2.Sub(nettime)/time.Second, delt/time.Second)
}
......@@ -29,6 +29,7 @@ type executor struct {
difficulty uint64
txs []*types.Transaction
api client.QueueProtocolAPI
gcli types.Chain33Client
execapi api.ExecutorAPI
receipts []*types.ReceiptData
}
......@@ -58,6 +59,8 @@ func newExecutor(ctx *executorCtx, exec *Executor, txs []*types.Transaction, rec
ctx: ctx,
txs: txs,
receipts: receipts,
api: exec.qclient,
gcli: exec.grpccli,
}
e.coinsAccount.SetDB(e.stateDB)
return e
......@@ -150,6 +153,7 @@ func (e *executor) setEnv(exec drivers.Driver) {
exec.SetEnv(e.height, e.blocktime, e.difficulty)
exec.SetBlockInfo(e.ctx.parentHash, e.ctx.mainHash, e.ctx.mainHeight)
exec.SetAPI(e.api)
exec.SetExecutorAPI(e.api, e.gcli)
e.execapi = exec.GetExecutorAPI()
exec.SetTxs(e.txs)
exec.SetReceipt(e.receipts)
......
......@@ -15,6 +15,7 @@ import (
clog "github.com/33cn/chain33/common/log"
log "github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/pluginmgr"
"github.com/33cn/chain33/rpc/grpcclient"
drivers "github.com/33cn/chain33/system/dapp"
// register drivers
......@@ -40,6 +41,7 @@ func DisableLog() {
type Executor struct {
client queue.Client
qclient client.QueueProtocolAPI
grpccli types.Chain33Client
pluginEnable map[string]bool
alias map[string]string
}
......@@ -102,6 +104,10 @@ func (exec *Executor) SetQueueClient(qcli queue.Client) {
if err != nil {
panic(err)
}
exec.grpccli, err = grpcclient.NewMainChainClient("")
if err != nil {
panic(err)
}
//recv 消息的处理
go func() {
for msg := range exec.client.Recv() {
......@@ -144,7 +150,7 @@ func (exec *Executor) procExecQuery(msg queue.Message) {
db.(*StateDB).enableMVCC()
driver.SetStateDB(db)
driver.SetAPI(exec.qclient)
driver.SetExecutorAPI(exec.qclient, exec.grpccli)
//查询的情况下下,执行器不做严格校验,allow,尽可能的加载执行器,并且做查询
ret, err := driver.Query(data.FuncName, data.Param)
......@@ -168,7 +174,6 @@ func (exec *Executor) procExecCheckTx(msg queue.Message) {
}
execute := newExecutor(ctx, exec, datas.Txs, nil)
execute.enableMVCC()
execute.api = exec.qclient
//返回一个列表表示成功还是失败
result := &types.ReceiptCheckTxList{}
for i := 0; i < len(datas.Txs); i++ {
......@@ -200,7 +205,6 @@ func (exec *Executor) procExecTxList(msg queue.Message) {
}
execute := newExecutor(ctx, exec, datas.Txs, nil)
execute.enableMVCC()
execute.api = exec.qclient
var receipts []*types.Receipt
index := 0
for i := 0; i < len(datas.Txs); i++ {
......@@ -270,7 +274,6 @@ func (exec *Executor) procExecAddBlock(msg queue.Message) {
}
execute := newExecutor(ctx, exec, b.Txs, datas.Receipts)
execute.enableMVCC()
execute.api = exec.qclient
var kvset types.LocalDBSet
for _, kv := range datas.KV {
execute.stateDB.Set(kv.Key, kv.Value)
......@@ -331,7 +334,6 @@ func (exec *Executor) procExecDelBlock(msg queue.Message) {
}
execute := newExecutor(ctx, exec, b.Txs, nil)
execute.enableMVCC()
execute.api = exec.qclient
var kvset types.LocalDBSet
for _, kv := range datas.KV {
execute.stateDB.Set(kv.Key, kv.Value)
......
package grpcclient_test
import (
"context"
"testing"
"time"
"github.com/33cn/chain33/client/mocks"
qmocks "github.com/33cn/chain33/queue/mocks"
"github.com/33cn/chain33/rpc"
"github.com/33cn/chain33/rpc/grpcclient"
"github.com/33cn/chain33/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"google.golang.org/grpc"
)
func TestMultipleGRPC(t *testing.T) {
qapi := new(mocks.QueueProtocolAPI)
qapi.On("Query", "ticket", "RandNumHash", mock.Anything).Return(&types.ReplyHash{Hash: []byte("hello")}, nil)
//testnode setup
rpcCfg := new(types.RPC)
rpcCfg.GrpcBindAddr = "127.0.0.1:8003"
rpcCfg.JrpcBindAddr = "127.0.0.1:8004"
rpcCfg.MainnetJrpcAddr = rpcCfg.JrpcBindAddr
rpcCfg.Whitelist = []string{"127.0.0.1", "0.0.0.0"}
rpcCfg.JrpcFuncWhitelist = []string{"*"}
rpcCfg.GrpcFuncWhitelist = []string{"*"}
rpc.InitCfg(rpcCfg)
server := rpc.NewGRpcServer(&qmocks.Client{}, qapi)
assert.NotNil(t, server)
go server.Listen()
time.Sleep(time.Second)
//一个IP 有效,一个IP 无效
paraRemoteGrpcClient := "127.0.0.1:8004,127.0.0.1:8003,127.0.0.1"
conn, err := grpc.Dial(grpcclient.NewMultipleURL(paraRemoteGrpcClient), grpc.WithInsecure())
assert.Nil(t, err)
grpcClient := types.NewChain33Client(conn)
param := &types.ReqRandHash{
ExecName: "ticket",
BlockNum: 5,
Hash: []byte("hello"),
}
reply, err := grpcClient.QueryRandNum(context.Background(), param)
assert.Nil(t, err)
assert.Equal(t, reply.Hash, []byte("hello"))
}
func TestNewParaClient(t *testing.T) {
qapi := new(mocks.QueueProtocolAPI)
qapi.On("Query", "ticket", "RandNumHash", mock.Anything).Return(&types.ReplyHash{Hash: []byte("hello")}, nil)
//testnode setup
rpcCfg := new(types.RPC)
rpcCfg.GrpcBindAddr = "127.0.0.1:8003"
rpcCfg.JrpcBindAddr = "127.0.0.1:8004"
rpcCfg.MainnetJrpcAddr = rpcCfg.JrpcBindAddr
rpcCfg.Whitelist = []string{"127.0.0.1", "0.0.0.0"}
rpcCfg.JrpcFuncWhitelist = []string{"*"}
rpcCfg.GrpcFuncWhitelist = []string{"*"}
rpc.InitCfg(rpcCfg)
server := rpc.NewGRpcServer(&qmocks.Client{}, qapi)
assert.NotNil(t, server)
go server.Listen()
time.Sleep(time.Second)
//一个IP 有效,一个IP 无效
paraRemoteGrpcClient := "127.0.0.1:8004,127.0.0.1:8003,127.0.0.1"
grpcClient, err := grpcclient.NewMainChainClient(paraRemoteGrpcClient)
assert.Nil(t, err)
param := &types.ReqRandHash{
ExecName: "ticket",
BlockNum: 5,
Hash: []byte("hello"),
}
reply, err := grpcClient.QueryRandNum(context.Background(), param)
assert.Nil(t, err)
assert.Equal(t, reply.Hash, []byte("hello"))
}
package grpcclient
import (
"github.com/33cn/chain33/types"
"google.golang.org/grpc"
)
//NewMainChainClient 创建一个平行链的 主链 grpc chain33 客户端
func NewMainChainClient(grpcaddr string) (types.Chain33Client, error) {
paraRemoteGrpcClient := types.Conf("config.consensus.sub.para").GStr("ParaRemoteGrpcClient")
if grpcaddr != "" {
paraRemoteGrpcClient = grpcaddr
}
if paraRemoteGrpcClient == "" {
paraRemoteGrpcClient = "127.0.0.1:8002"
}
conn, err := grpc.Dial(NewMultipleURL(paraRemoteGrpcClient), grpc.WithInsecure())
if err != nil {
return nil, err
}
grpcClient := types.NewChain33Client(conn)
return grpcClient, nil
}
package grpcclient
import (
"errors"
"fmt"
"net"
"strings"
"google.golang.org/grpc/resolver"
)
// Scheme 自定义grpc负载局衡名
const scheme = "multiple"
// Separator url分隔符
const separator = ":///"
// MultiPleHostsBalancerPrefix url前缀
const multiPleHostsBalancerPrefix = scheme + separator
// defaultGrpcPort 默认grpc端口
const defaultGrpcPort = "8802"
func parseTarget(target, defaultPort string) (host, port string, err error) {
if target == "" {
return "", "", errors.New("multiple resolver: missing address")
}
if ip := net.ParseIP(target); ip != nil {
return target, defaultPort, nil
}
if host, port, err = net.SplitHostPort(target); err == nil {
if port == "" {
return "", "", errors.New("multiple resolver: missing port after port-separator colon")
}
if host == "" {
host = "localhost"
}
return host, port, nil
}
if host, port, err = net.SplitHostPort(target + ":" + defaultPort); err == nil {
return host, port, nil
}
return "", "", fmt.Errorf("invalid target address %v, error info: %v", target, err)
}
type multipleBuilder struct{}
func (*multipleBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOption) (resolver.Resolver, error) {
r := &multipleResolver{
target: target,
cc: cc,
}
urls := strings.Split(target.Endpoint, ",")
if len(urls) < 1 {
return nil, fmt.Errorf("invalid target address %v", target)
}
for _, url := range urls {
host, port, err := parseTarget(url, defaultGrpcPort)
if err != nil {
return nil, err
}
if net.ParseIP(host) != nil {
r.addrs = append(r.addrs, resolver.Address{Addr: host + ":" + port})
}
}
r.start()
return r, nil
}
func (*multipleBuilder) Scheme() string {
return scheme
}
type multipleResolver struct {
target resolver.Target
cc resolver.ClientConn
addrs []resolver.Address
}
func (r *multipleResolver) start() {
r.cc.NewAddress(r.addrs)
}
func (*multipleResolver) ResolveNow(o resolver.ResolveNowOption) {}
func (*multipleResolver) Close() {}
func init() {
resolver.Register(&multipleBuilder{})
}
//NewMultipleURL 创建url
func NewMultipleURL(url string) string {
return multiPleHostsBalancerPrefix + url
}
......@@ -12,6 +12,7 @@ import (
"github.com/33cn/chain33/client"
"github.com/33cn/chain33/pluginmgr"
"github.com/33cn/chain33/queue"
_ "github.com/33cn/chain33/rpc/grpcclient" // register grpc multiple resolver
"github.com/33cn/chain33/types"
"golang.org/x/net/context"
"google.golang.org/grpc"
......@@ -197,6 +198,9 @@ func InitCfg(cfg *types.RPC) {
// New produce a rpc by cfg
func New(cfg *types.RPC) *RPC {
InitCfg(cfg)
if cfg.EnableTrace {
grpc.EnableTracing = true
}
return &RPC{cfg: cfg}
}
......
......@@ -103,7 +103,7 @@ func DecodeTx(tx *types.Transaction) (*Transaction, error) {
}
var pljson json.RawMessage
if pl != nil {
pljson, _ = types.PBToJSON(pl)
pljson, _ = types.PBToJSONUTF8(pl)
}
result := &Transaction{
Execer: string(tx.Execer),
......
......@@ -11,18 +11,12 @@ import (
"io"
"os"
"strings"
"time"
"github.com/33cn/chain33/rpc/jsonclient"
commandtypes "github.com/33cn/chain33/system/dapp/commands/types"
"github.com/33cn/chain33/types"
"github.com/spf13/cobra"
)
const (
defaultPrivacyMixCount = 16
)
// BTYCmd bty command
func BTYCmd() *cobra.Command {
cmd := &cobra.Command{
......@@ -35,9 +29,6 @@ func BTYCmd() *cobra.Command {
CreateRawWithdrawCmd(),
CreateRawSendToExecCmd(),
CreateTxGroupCmd(),
CreatePub2PrivTxCmd(),
CreatePriv2PrivTxCmd(),
CreatePriv2PubTxCmd(),
)
return cmd
}
......@@ -54,9 +45,6 @@ func CoinsCmd() *cobra.Command {
CreateRawWithdrawCmd(),
CreateRawSendToExecCmd(),
CreateTxGroupCmd(),
CreatePub2PrivTxCmd(),
CreatePriv2PrivTxCmd(),
CreatePriv2PubTxCmd(),
)
return cmd
}
......@@ -321,184 +309,3 @@ func createTxGroup(cmd *cobra.Command, args []string) {
grouptx := hex.EncodeToString(types.Encode(newtx))
fmt.Println(grouptx)
}
// CreatePub2PrivTxCmd create a public to privacy transaction
func CreatePub2PrivTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "pub2priv",
Short: "Create a public to privacy transaction",
Run: createPub2PrivTx,
}
createPub2PrivTxFlags(cmd)
return cmd
}
func createPub2PrivTxFlags(cmd *cobra.Command) {
cmd.Flags().StringP("pubkeypair", "p", "", "public key pair")
cmd.MarkFlagRequired("pubkeypair")
cmd.Flags().Float64P("amount", "a", 0.0, "transfer amount, at most 4 decimal places")
cmd.MarkFlagRequired("amount")
cmd.Flags().StringP("tokenname", "", "BTY", "token name")
cmd.Flags().StringP("note", "n", "", "note for transaction")
cmd.Flags().Int64P("expire", "", 0, "transfer expire, default one hour")
cmd.Flags().IntP("expiretype", "", 1, "0: height 1: time default is 1")
}
func createPub2PrivTx(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
pubkeypair, _ := cmd.Flags().GetString("pubkeypair")
amount := commandtypes.GetAmountValue(cmd, "amount")
tokenname, _ := cmd.Flags().GetString("tokenname")
note, _ := cmd.Flags().GetString("note")
expire, _ := cmd.Flags().GetInt64("expire")
expiretype, _ := cmd.Flags().GetInt("expiretype")
if expiretype == 0 {
if expire <= 0 {
fmt.Println("Invalid expire. expire must large than 0 in expiretype==0, expire", expire)
return
}
} else if expiretype == 1 {
if expire <= 0 {
expire = int64(time.Hour / time.Second)
}
} else {
fmt.Println("Invalid expiretype", expiretype)
return
}
params := types.ReqCreateTransaction{
Tokenname: tokenname,
Type: types.PrivacyTypePublic2Privacy,
Amount: amount,
Note: note,
Pubkeypair: pubkeypair,
Expire: expire,
}
ctx := jsonclient.NewRPCCtx(rpcLaddr, "privacy.CreateRawTransaction", params, nil)
ctx.RunWithoutMarshal()
}
// CreatePriv2PrivTxCmd create a privacy to privacy transaction
func CreatePriv2PrivTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "priv2priv",
Short: "Create a privacy to privacy transaction",
Run: createPriv2PrivTx,
}
createPriv2PrivTxFlags(cmd)
return cmd
}
func createPriv2PrivTxFlags(cmd *cobra.Command) {
cmd.Flags().StringP("pubkeypair", "p", "", "public key pair")
cmd.MarkFlagRequired("pubkeypair")
cmd.Flags().Float64P("amount", "a", 0.0, "transfer amount, at most 4 decimal places")
cmd.MarkFlagRequired("amount")
cmd.Flags().StringP("sender", "s", "", "account address")
cmd.MarkFlagRequired("sender")
cmd.Flags().StringP("tokenname", "t", "BTY", "token name")
cmd.Flags().StringP("note", "n", "", "note for transaction")
cmd.Flags().Int64P("expire", "", 0, "transfer expire, default one hour")
cmd.Flags().IntP("expiretype", "", 1, "0: height 1: time default is 1")
}
func createPriv2PrivTx(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
pubkeypair, _ := cmd.Flags().GetString("pubkeypair")
amount := commandtypes.GetAmountValue(cmd, "amount")
tokenname, _ := cmd.Flags().GetString("tokenname")
note, _ := cmd.Flags().GetString("note")
sender, _ := cmd.Flags().GetString("sender")
expire, _ := cmd.Flags().GetInt64("expire")
expiretype, _ := cmd.Flags().GetInt("expiretype")
if expiretype == 0 {
if expire <= 0 {
fmt.Println("Invalid expire. expire must large than 0 in expiretype==0, expire", expire)
return
}
} else if expiretype == 1 {
if expire <= 0 {
expire = int64(time.Hour / time.Second)
}
} else {
fmt.Println("Invalid expiretype", expiretype)
return
}
params := types.ReqCreateTransaction{
Tokenname: tokenname,
Type: types.PrivacyTypePrivacy2Privacy,
Amount: amount,
Note: note,
Pubkeypair: pubkeypair,
From: sender,
Mixcount: defaultPrivacyMixCount,
Expire: expire,
}
ctx := jsonclient.NewRPCCtx(rpcLaddr, "privacy.CreateRawTransaction", params, nil)
ctx.RunWithoutMarshal()
}
// CreatePriv2PubTxCmd create a privacy to public transaction
func CreatePriv2PubTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "priv2pub",
Short: "Create a privacy to public transaction",
Run: createPriv2PubTx,
}
createPriv2PubTxFlags(cmd)
return cmd
}
func createPriv2PubTxFlags(cmd *cobra.Command) {
cmd.Flags().Float64P("amount", "a", 0.0, "transfer amount, at most 4 decimal places")
cmd.MarkFlagRequired("amount")
cmd.Flags().StringP("from", "f", "", "from account address")
cmd.MarkFlagRequired("from")
cmd.Flags().StringP("to", "o", "", "to account address")
cmd.MarkFlagRequired("to")
cmd.Flags().StringP("tokenname", "t", "BTY", "token name")
cmd.Flags().StringP("note", "n", "", "note for transaction")
cmd.Flags().Int64P("expire", "", 0, "transfer expire, default one hour")
cmd.Flags().IntP("expiretype", "", 1, "0: height 1: time default is 1")
}
func createPriv2PubTx(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
amount := commandtypes.GetAmountValue(cmd, "amount")
tokenname, _ := cmd.Flags().GetString("tokenname")
from, _ := cmd.Flags().GetString("from")
to, _ := cmd.Flags().GetString("to")
note, _ := cmd.Flags().GetString("note")
expire, _ := cmd.Flags().GetInt64("expire")
expiretype, _ := cmd.Flags().GetInt("expiretype")
if expiretype == 0 {
if expire <= 0 {
fmt.Println("Invalid expire. expire must large than 0 in expiretype==0, expire", expire)
return
}
} else if expiretype == 1 {
if expire <= 0 {
expire = int64(time.Hour / time.Second)
}
} else {
fmt.Println("Invalid expiretype", expiretype)
return
}
params := types.ReqCreateTransaction{
Tokenname: tokenname,
Type: types.PrivacyTypePrivacy2Public,
Amount: amount,
Note: note,
From: from,
To: to,
Mixcount: defaultPrivacyMixCount,
Expire: expire,
}
ctx := jsonclient.NewRPCCtx(rpcLaddr, "privacy.CreateRawTransaction", params, nil)
ctx.RunWithoutMarshal()
}
......@@ -58,6 +58,7 @@ type Driver interface {
Query(funcName string, params []byte) (types.Message, error)
IsFree() bool
SetAPI(client.QueueProtocolAPI)
SetExecutorAPI(queueapi client.QueueProtocolAPI, chain33api types.Chain33Client)
SetTxs(txs []*types.Transaction)
SetReceipt(receipts []*types.ReceiptData)
......@@ -129,7 +130,11 @@ func (d *DriverBase) GetFuncMap() map[string]reflect.Method {
// SetAPI set queue protocol api
func (d *DriverBase) SetAPI(queueapi client.QueueProtocolAPI) {
d.api = queueapi
d.execapi = api.New(queueapi, "")
}
// SetExecutorAPI set queue protocol api
func (d *DriverBase) SetExecutorAPI(queueapi client.QueueProtocolAPI, chain33api types.Chain33Client) {
d.execapi = api.New(queueapi, chain33api)
}
// GetAPI return queue protocol api
......
......@@ -5,6 +5,7 @@ import (
"time"
"github.com/33cn/chain33/client/mocks"
"github.com/33cn/chain33/rpc/grpcclient"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/util"
"github.com/stretchr/testify/assert"
......@@ -81,6 +82,9 @@ func TestDriverAPI(t *testing.T) {
demo.SetLocalDB(kvdb)
demo.SetStateDB(kvdb)
demo.SetAPI(&mocks.QueueProtocolAPI{})
gcli, err := grpcclient.NewMainChainClient("")
assert.Nil(t, err)
demo.SetExecutorAPI(&mocks.QueueProtocolAPI{}, gcli)
assert.NotNil(t, demo.GetAPI())
assert.NotNil(t, demo.GetExecutorAPI())
types.SetTitleOnlyForTest("chain33")
......
......@@ -140,6 +140,7 @@ type RPC struct {
GrpcFuncBlacklist []string `protobuf:"bytes,8,rep,name=grpcFuncBlacklist" json:"grpcFuncBlacklist,omitempty"`
MainnetJrpcAddr string `protobuf:"bytes,9,opt,name=mainnetJrpcAddr" json:"mainnetJrpcAddr,omitempty"`
EnableTLS bool `protobuf:"varint,10,opt,name=enableTLS" json:"enableTLS,omitempty"`
EnableTrace bool `protobuf:"varint,10,opt,name=enableTrace" json:"enableTrace,omitempty"`
CertFile string `protobuf:"varint,11,opt,name=certFile" json:"certFile,omitempty"`
KeyFile string `protobuf:"varint,12,opt,name=keyFile" json:"keyFile,omitempty"`
}
......
......@@ -447,6 +447,20 @@ func getTo(payload interface{}) (string, bool) {
return "", false
}
//IsAssetsTransfer 是否是资产转移相关的交易
func IsAssetsTransfer(payload interface{}) bool {
if _, ok := payload.(*AssetsTransfer); ok {
return true
}
if _, ok := payload.(*AssetsWithdraw); ok {
return true
}
if _, ok := payload.(*AssetsTransferToExec); ok {
return true
}
return false
}
//Amounter 转账金额
type Amounter interface {
GetAmount() int64
......
......@@ -133,3 +133,10 @@ func TestCallCreateTx(t *testing.T) {
fee, _ = tx.GetRealFee(GInt("MinFee"))
assert.Equal(t, tx.Fee, fee)
}
func TestIsAssetsTransfer(t *testing.T) {
assert.Equal(t, true, IsAssetsTransfer(&AssetsTransfer{}))
assert.Equal(t, true, IsAssetsTransfer(&AssetsWithdraw{}))
assert.Equal(t, true, IsAssetsTransfer(&AssetsTransferToExec{}))
assert.Equal(t, false, IsAssetsTransfer(&Transaction{}))
}
......@@ -54,6 +54,7 @@ import (
"strconv"
"strings"
"time"
"unicode/utf8"
"github.com/33cn/chain33/common"
"github.com/golang/protobuf/proto"
......@@ -72,6 +73,9 @@ type Marshaler struct {
// Whether to render fields with zero values.
EmitDefaults bool
//Enable utf8 bytes to string
EnableUTF8BytesToString bool
// A string to indent each level by. The presence of this field will
// also cause a space to appear between the field separator and
// value, and for newlines to be appear between fields and array
......@@ -532,7 +536,13 @@ func (m *Marshaler) marshalValue(out *errWriter, prop *proto.Properties, v refle
return out.err
}
out.write(`"`)
out.write(common.ToHex(v.Interface().([]byte)))
data := v.Interface().([]byte)
//开启这个选项后,会把utf8的字符串转化成string,而不会弄成hex
if m.EnableUTF8BytesToString && utf8.Valid(data) {
out.write(string(data))
} else {
out.write(common.ToHex(data))
}
out.write(`"`)
return out.err
}
......@@ -672,6 +682,9 @@ type Unmarshaler struct {
// failing to unmarshal.
AllowUnknownFields bool
//Enable utf8 bytes to string
EnableUTF8BytesToString bool
// A custom URL resolver to use when unmarshaling Any messages from JSON.
// If unset, the default resolution strategy is to extract the
// fully-qualified type name from the type URL and pass that to
......@@ -1041,7 +1054,7 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
if err != nil {
return err
}
b, err := parseBytes(hexstr)
b, err := parseBytes(hexstr, u.EnableUTF8BytesToString)
if err != nil {
return err
}
......@@ -1317,7 +1330,7 @@ func checkRequiredFieldsInValue(v reflect.Value) error {
//ErrBytesFormat 错误的bytes 类型
var ErrBytesFormat = errors.New("ErrBytesFormat")
func parseBytes(jsonstr string) ([]byte, error) {
func parseBytes(jsonstr string, enableUTF8BytesToString bool) ([]byte, error) {
if jsonstr == "" {
return []byte{}, nil
}
......@@ -1327,5 +1340,10 @@ func parseBytes(jsonstr string) ([]byte, error) {
if strings.HasPrefix(jsonstr, "0x") || strings.HasPrefix(jsonstr, "0X") {
return common.FromHex(jsonstr)
}
//字符串不是 hex 格式, 也不是 str:// 格式,但是是一个普通的utf8 字符串
//那么强制转化为bytes, 注意这个选项默认不开启.
if utf8.ValidString(jsonstr) && enableUTF8BytesToString {
return []byte(jsonstr), nil
}
return nil, ErrBytesFormat
}
......@@ -214,6 +214,12 @@ func JSONToPB(data []byte, msg proto.Message) error {
return jsonpb.Unmarshal(bytes.NewReader(data), msg)
}
//JSONToPBUTF8 默认解码utf8的字符串成bytes
func JSONToPBUTF8(data []byte, msg proto.Message) error {
decode := &jsonpb.Unmarshaler{EnableUTF8BytesToString: true}
return decode.Unmarshal(bytes.NewReader(data), msg)
}
//Hash 计算叶子节点的hash
func (leafnode *LeafNode) Hash() []byte {
data, err := proto.Marshal(leafnode)
......@@ -430,6 +436,16 @@ func PBToJSON(r Message) ([]byte, error) {
return buf.Bytes(), nil
}
// PBToJSONUTF8 消息类型转换
func PBToJSONUTF8(r Message) ([]byte, error) {
encode := &jsonpb.Marshaler{EmitDefaults: true, EnableUTF8BytesToString: true}
var buf bytes.Buffer
if err := encode.Marshal(&buf, r); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
//MustPBToJSON panic when error
func MustPBToJSON(req Message) []byte {
data, err := PBToJSON(req)
......
......@@ -153,6 +153,30 @@ func TestProtoToJson(t *testing.T) {
assert.Equal(t, dr.Msg, []byte{})
}
func TestJsonpbUTF8(t *testing.T) {
r := &Reply{Msg: []byte("OK")}
b, err := PBToJSONUTF8(r)
assert.Nil(t, err)
assert.Equal(t, b, []byte(`{"isOk":false,"msg":"OK"}`))
var newreply Reply
err = JSONToPBUTF8(b, &newreply)
assert.Nil(t, err)
assert.Equal(t, r, &newreply)
}
func TestJsonpb(t *testing.T) {
r := &Reply{Msg: []byte("OK")}
b, err := PBToJSON(r)
assert.Nil(t, err)
assert.Equal(t, b, []byte(`{"isOk":false,"msg":"0x4f4b"}`))
var newreply Reply
err = JSONToPB(b, &newreply)
assert.Nil(t, err)
assert.Equal(t, r, &newreply)
}
func TestHex(t *testing.T) {
s := "0x4f4b"
b, err := common.FromHex(s)
......
......@@ -40,8 +40,6 @@ import (
"github.com/33cn/chain33/store"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/wallet"
"golang.org/x/net/trace"
"google.golang.org/grpc"
"google.golang.org/grpc/grpclog"
)
......@@ -116,9 +114,6 @@ func RunChain33(name string) {
http.ListenAndServe("localhost:6060", nil)
}
}()
//set trace
grpc.EnableTracing = true
go startTrace()
//set maxprocs
runtime.GOMAXPROCS(cpuNum)
//开始区块链模块加载
......@@ -201,16 +196,6 @@ func RunChain33(name string) {
q.Start()
}
// 开启trace
func startTrace() {
trace.AuthRequest = func(req *http.Request) (any, sensitive bool) {
return true, true
}
go http.ListenAndServe("localhost:50051", nil)
log.Info("Trace listen on localhost:50051")
}
func createFile(filename string) (*os.File, error) {
f, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
......
......@@ -95,7 +95,7 @@ func (wallet *Wallet) ProcSignRawTx(unsigned *types.ReqSignRawTx) (string, error
return "", err
}
tx.SetExpire(time.Duration(expire))
if policy, ok := wcom.PolicyContainer[string(tx.Execer)]; ok {
if policy, ok := wcom.PolicyContainer[string(types.GetParaExec(tx.Execer))]; ok {
// 尝试让策略自己去完成签名
needSysSign, signtx, err := policy.SignTransaction(key, unsigned)
if !needSysSign {
......@@ -909,7 +909,7 @@ func (wallet *Wallet) ProcWalletAddBlock(block *types.BlockDetail) {
newbatch := wallet.walletStore.NewBatch(true)
for index := 0; index < txlen; index++ {
tx := block.Block.Txs[index]
execer := string(tx.Execer)
execer := string(types.GetParaExec(tx.Execer))
// 执行钱包业务逻辑策略
if policy, ok := wcom.PolicyContainer[execer]; ok {
wtxdetail := policy.OnAddBlockTx(block, tx, int32(index), newbatch)
......@@ -1031,7 +1031,7 @@ func (wallet *Wallet) ProcWalletDelBlock(block *types.BlockDetail) {
heightstr := fmt.Sprintf("%018d", blockheight)
tx := block.Block.Txs[index]
execer := string(tx.Execer)
execer := string(types.GetParaExec(tx.Execer))
// 执行钱包业务逻辑策略
if policy, ok := wcom.PolicyContainer[execer]; ok {
wtxdetail := policy.OnDeleteBlockTx(block, tx, int32(index), newbatch)
......
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