Commit 86b5aa01 authored by vipwzw's avatar vipwzw

update oracle

parent 6aa5072a
......@@ -12,6 +12,7 @@ chain33_raft-1
build/datadir
build/bityuan*
build/para
build/cli
build/execblock
build/relayd
build/relayd.toml
......
......@@ -11,6 +11,7 @@ import (
_ "github.com/33cn/plugin/plugin/dapp/lottery" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/multisig" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/norm" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/oracle" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/paracross" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/pokerbull" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/privacy" //auto gen
......
/*
* 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 commands
import (
"fmt"
"strconv"
"strings"
"time"
"github.com/33cn/chain33/rpc/jsonclient"
rpctypes "github.com/33cn/chain33/rpc/types"
"github.com/33cn/chain33/types"
oraclety "github.com/33cn/plugin/plugin/dapp/oracle/types"
"github.com/spf13/cobra"
)
// OracleCmd 预言机命令行
func OracleCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "oracle",
Short: "oracle management",
Args: cobra.MinimumNArgs(1),
}
cmd.AddCommand(
OraclePublishEventRawTxCmd(),
OracleAbortEventRawTxCmd(),
OraclePrePublishResultRawTxCmd(),
OracleAbortPrePubResultRawTxCmd(),
OraclePublishResultRawTxCmd(),
OracleQueryRawTxCmd(),
)
return cmd
}
// OraclePublishEventRawTxCmd 发布事件
func OraclePublishEventRawTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "publish_event",
Short: "publish a new event",
Run: publishEvent,
}
addPublishEventFlags(cmd)
return cmd
}
func addPublishEventFlags(cmd *cobra.Command) {
cmd.Flags().StringP("type", "t", "", "event type, such as \"football\"")
cmd.MarkFlagRequired("type")
cmd.Flags().StringP("subtype", "s", "", "event subtype, such as \"Premier League\"")
cmd.MarkFlagRequired("subtype")
cmd.Flags().StringP("time", "m", "", "time that event result may be shown, such as \"2019-01-21 15:30:00\"")
cmd.MarkFlagRequired("time")
cmd.Flags().StringP("content", "c", "", "event content, such as '{\"team1\":\"ChelSea\", \"team2\":\"Manchester\",\"resultType\":\"score\"}'")
cmd.MarkFlagRequired("content")
cmd.Flags().StringP("introduction", "i", "", "event introduction, such as \"guess the sore result of football game between ChelSea and Manchester in 2019-01-21 14:00:00\"")
cmd.MarkFlagRequired("introduction")
}
func publishEvent(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ty, _ := cmd.Flags().GetString("type")
subType, _ := cmd.Flags().GetString("subtype")
introduction, _ := cmd.Flags().GetString("introduction")
timeString, _ := cmd.Flags().GetString("time")
content, _ := cmd.Flags().GetString("content")
layout := "2006-01-02 15:04:05"
t, err := time.Parse(layout, timeString)
if err != nil {
fmt.Printf("time error:%v\n", err.Error())
return
}
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(oraclety.OracleX),
ActionName: oraclety.CreateEventPublishTx,
Payload: []byte(fmt.Sprintf("{\"type\":\"%s\",\"subType\":\"%s\",\"time\":%d, \"content\":\"%s\", \"introduction\":\"%s\"}", ty, subType, t.Unix(), content, introduction)),
}
var res string
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, &res)
ctx.RunWithoutMarshal()
}
// OracleAbortEventRawTxCmd 取消发布事件
func OracleAbortEventRawTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "abort_publish_event",
Short: "abort publish the event",
Run: abortPublishEvent,
}
addAbortPublishEventFlags(cmd)
return cmd
}
func addAbortPublishEventFlags(cmd *cobra.Command) {
cmd.Flags().StringP("eventID", "e", "", "eventID")
cmd.MarkFlagRequired("eventID")
}
func abortPublishEvent(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
eventID, _ := cmd.Flags().GetString("eventID")
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(oraclety.OracleX),
ActionName: oraclety.CreateAbortEventPublishTx,
Payload: []byte(fmt.Sprintf("{\"eventID\":\"%s\"}", eventID)),
}
var res string
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, &res)
ctx.RunWithoutMarshal()
}
// OraclePrePublishResultRawTxCmd 预发布结果
func OraclePrePublishResultRawTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "prepublish_result",
Short: "pre publish result of a new event",
Run: prePublishResult,
}
addPrePublishResultFlags(cmd)
return cmd
}
func addPrePublishResultFlags(cmd *cobra.Command) {
cmd.Flags().StringP("eventID", "e", "", "eventID")
cmd.MarkFlagRequired("eventID")
cmd.Flags().StringP("source", "s", "", "source where result from")
cmd.MarkFlagRequired("source")
cmd.Flags().StringP("result", "r", "", "result string")
cmd.MarkFlagRequired("result")
}
func prePublishResult(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
eventID, _ := cmd.Flags().GetString("eventID")
source, _ := cmd.Flags().GetString("source")
result, _ := cmd.Flags().GetString("result")
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(oraclety.OracleX),
ActionName: oraclety.CreatePrePublishResultTx,
Payload: []byte(fmt.Sprintf("{\"eventID\":\"%s\", \"source\":\"%s\", \"result\":\"%s\"}", eventID, source, result)),
}
var res string
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, &res)
ctx.RunWithoutMarshal()
}
// OracleAbortPrePubResultRawTxCmd 取消预发布的事件结果
func OracleAbortPrePubResultRawTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "abort_result",
Short: "abort result pre-published before",
Run: abortPrePubResult,
}
addAbortPrePubResultFlags(cmd)
return cmd
}
func addAbortPrePubResultFlags(cmd *cobra.Command) {
cmd.Flags().StringP("eventID", "e", "", "eventID")
cmd.MarkFlagRequired("eventID")
}
func abortPrePubResult(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
eventID, _ := cmd.Flags().GetString("eventID")
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(oraclety.OracleX),
ActionName: oraclety.CreateAbortResultPrePublishTx,
Payload: []byte(fmt.Sprintf("{\"eventID\":\"%s\"}", eventID)),
}
var res string
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, &res)
ctx.RunWithoutMarshal()
}
// OraclePublishResultRawTxCmd 发布事件结果
func OraclePublishResultRawTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "publish_result",
Short: "publish final result event",
Run: publishResult,
}
addPublishResultFlags(cmd)
return cmd
}
func addPublishResultFlags(cmd *cobra.Command) {
cmd.Flags().StringP("eventID", "e", "", "eventID")
cmd.MarkFlagRequired("eventID")
cmd.Flags().StringP("source", "s", "", "source where result from")
cmd.MarkFlagRequired("source")
cmd.Flags().StringP("result", "r", "", "result string, such as \"{\"team1\":3, \"team2\":2}\"")
cmd.MarkFlagRequired("result")
}
func publishResult(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
eventID, _ := cmd.Flags().GetString("eventID")
source, _ := cmd.Flags().GetString("source")
result, _ := cmd.Flags().GetString("result")
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(oraclety.OracleX),
ActionName: oraclety.CreateResultPublishTx,
Payload: []byte(fmt.Sprintf("{\"eventID\":\"%s\", \"source\":\"%s\", \"result\":\"%s\"}", eventID, source, result)),
}
var res string
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, &res)
ctx.RunWithoutMarshal()
}
// OracleQueryRawTxCmd 查询事件
func OracleQueryRawTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "query",
Short: "query event and event status",
Run: oracleQuery,
}
addOracleQueryFlags(cmd)
return cmd
}
func addOracleQueryFlags(cmd *cobra.Command) {
cmd.Flags().StringP("last_eventID", "l", "", "last eventID, to get next page data")
cmd.MarkFlagRequired("last_eventID")
cmd.Flags().StringP("type", "t", "", "event type, such as \"football\"")
cmd.MarkFlagRequired("type")
cmd.Flags().StringP("status", "s", "", "status, number 1-5")
cmd.MarkFlagRequired("status")
cmd.Flags().StringP("addr", "a", "", "address of event creator")
cmd.MarkFlagRequired("addr")
cmd.Flags().StringP("eventIDs", "d", "", "eventIDs, used for query eventInfo, use comma between many ids")
cmd.MarkFlagRequired("eventIDs")
}
func oracleQuery(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
lastEventID, _ := cmd.Flags().GetString("last_eventID")
eventIDs, _ := cmd.Flags().GetString("eventIDs")
ty, _ := cmd.Flags().GetString("type")
statusStr, _ := cmd.Flags().GetString("status")
status, _ := strconv.ParseInt(statusStr, 10, 32)
addr, _ := cmd.Flags().GetString("addr")
var params rpctypes.Query4Jrpc
params.Execer = oraclety.OracleX
req := &oraclety.QueryEventID{
Status: int32(status),
Addr: addr,
Type: ty,
EventID: lastEventID,
}
params.Payload = types.MustPBToJSON(req)
if eventIDs != "" {
params.FuncName = oraclety.FuncNameQueryOracleListByIDs
var eIDs []string
ids := strings.Split(eventIDs, ",")
eIDs = append(eIDs, ids...)
req := &oraclety.QueryOracleInfos{EventID: eIDs}
params.Payload = types.MustPBToJSON(req)
var res oraclety.ReplyOracleStatusList
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
} else if statusStr != "" {
if status < 0 || status > 5 {
fmt.Println("Error: status must be 1-5")
cmd.Help()
return
} else if addr != "" {
params.FuncName = oraclety.FuncNameQueryEventIDByAddrAndStatus
} else if ty != "" {
params.FuncName = oraclety.FuncNameQueryEventIDByTypeAndStatus
} else {
params.FuncName = oraclety.FuncNameQueryEventIDByStatus
}
var res oraclety.ReplyEventIDs
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
} else {
fmt.Println("Error: requeres at least one of eventID, eventIDs, status")
cmd.Help()
}
}
/*
* 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 executor
/*
数据发布合约流程
1 由管理员通过manage合约增加问题发布者信息,数据预发布者信息,数据最终发布者信息
2 问题发布者发布问题
2.1 问题发布者撤销问题
3 数据预发布者预发布数据
3.1 数据预发布者撤销预发布数据
4 数据最终发布者发布数据
5 通过查询接口查询问题结果
*/
/*
* 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 executor
import (
"github.com/33cn/chain33/types"
oty "github.com/33cn/plugin/plugin/dapp/oracle/types"
)
func (o *oracle) Exec_EventPublish(payload *oty.EventPublish, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newOracleAction(o, tx, index)
return action.eventPublish(payload)
}
func (o *oracle) Exec_EventAbort(payload *oty.EventAbort, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newOracleAction(o, tx, index)
return action.eventAbort(payload)
}
func (o *oracle) Exec_ResultPrePublish(payload *oty.ResultPrePublish, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newOracleAction(o, tx, index)
return action.resultPrePublish(payload)
}
func (o *oracle) Exec_ResultAbort(payload *oty.ResultAbort, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newOracleAction(o, tx, index)
return action.resultAbort(payload)
}
func (o *oracle) Exec_ResultPublish(payload *oty.ResultPublish, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newOracleAction(o, tx, index)
return action.resultPublish(payload)
}
/*
* 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 executor
import (
"github.com/33cn/chain33/types"
oty "github.com/33cn/plugin/plugin/dapp/oracle/types"
)
func (o *oracle) execDelLocal(receipt *types.ReceiptData) (*types.LocalDBSet, error) {
set := &types.LocalDBSet{}
table := oty.NewTable(o.GetLocalDB())
for _, item := range receipt.Logs {
var oraclelog oty.ReceiptOracle
err := types.Decode(item.Log, &oraclelog)
if err != nil {
return nil, err
}
//回滚时如果状态为EventPublished则删除记录,否则回滚至上一状态
if oraclelog.Status == oty.EventPublished {
err = table.Del([]byte(oraclelog.EventID))
if err != nil {
return nil, err
}
} else {
oraclelog.Status = oraclelog.PreStatus
err = table.Replace(&oraclelog)
if err != nil {
return nil, err
}
}
kvs, err := table.Save()
if err != nil {
return nil, err
}
set.KV = append(set.KV, kvs...)
}
return set, nil
}
func (o *oracle) ExecDelLocal_EventPublish(payload *oty.EventPublish, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return o.execDelLocal(receiptData)
}
func (o *oracle) ExecDelLocal_EventAbort(payload *oty.EventAbort, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return o.execDelLocal(receiptData)
}
func (o *oracle) ExecDelLocal_ResultPrePublish(payload *oty.ResultPrePublish, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return o.execDelLocal(receiptData)
}
func (o *oracle) ExecDelLocal_ResultAbort(payload *oty.ResultAbort, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return o.execDelLocal(receiptData)
}
func (o *oracle) ExecDelLocal_ResultPublish(payload *oty.ResultPublish, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return o.execDelLocal(receiptData)
}
/*
* 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 executor
import (
"github.com/33cn/chain33/types"
oty "github.com/33cn/plugin/plugin/dapp/oracle/types"
)
func (o *oracle) execLocal(receipt *types.ReceiptData) (*types.LocalDBSet, error) {
set := &types.LocalDBSet{}
if receipt.GetTy() != types.ExecOk {
return set, nil
}
table := oty.NewTable(o.GetLocalDB())
for _, item := range receipt.Logs {
if item.Ty >= oty.TyLogEventPublish && item.Ty <= oty.TyLogResultPublish {
var oraclelog oty.ReceiptOracle
err := types.Decode(item.Log, &oraclelog)
if err != nil {
return nil, err
}
err = table.Replace(&oraclelog)
if err != nil {
return nil, err
}
kvs, err := table.Save()
if err != nil {
return nil, err
}
set.KV = append(set.KV, kvs...)
}
}
return set, nil
}
func (o *oracle) ExecLocal_EventPublish(payload *oty.EventPublish, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return o.execLocal(receiptData)
}
func (o *oracle) ExecLocal_EventAbort(payload *oty.EventAbort, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return o.execLocal(receiptData)
}
func (o *oracle) ExecLocal_ResultPrePublish(payload *oty.ResultPrePublish, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return o.execLocal(receiptData)
}
func (o *oracle) ExecLocal_ResultAbort(payload *oty.ResultAbort, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return o.execLocal(receiptData)
}
func (o *oracle) ExecLocal_ResultPublish(payload *oty.ResultPublish, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return o.execLocal(receiptData)
}
/*
* 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 executor
import (
log "github.com/33cn/chain33/common/log/log15"
drivers "github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
oty "github.com/33cn/plugin/plugin/dapp/oracle/types"
)
var olog = log.New("module", "execs.oracle")
var driverName = oty.OracleX
// Init 执行器初始化
func Init(name string, sub []byte) {
drivers.Register(newOracle().GetName(), newOracle, types.GetDappFork(driverName, "Enable"))
}
// GetName 获取oracle执行器名
func GetName() string {
return newOracle().GetName()
}
func newOracle() drivers.Driver {
t := &oracle{}
t.SetChild(t)
t.SetExecutorType(types.LoadExecutorType(driverName))
return t
}
func init() {
ety := types.LoadExecutorType(driverName)
ety.InitFuncList(types.ListMethod(&oracle{}))
}
// oracle driver
type oracle struct {
drivers.DriverBase
}
func (ora *oracle) GetDriverName() string {
return oty.OracleX
}
This diff is collapsed.
/*
* 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 executor
import (
"github.com/33cn/chain33/types"
oty "github.com/33cn/plugin/plugin/dapp/oracle/types"
)
//从statedb 读取原始数据
func (o *oracle) Query_QueryOraclesByIDs(in *oty.QueryOracleInfos) (types.Message, error) {
return getOracleLisByIDs(o.GetStateDB(), in)
}
//通过状态查询ids
func (o *oracle) Query_QueryEventIDsByStatus(in *oty.QueryEventID) (types.Message, error) {
eventIds, err := getEventIDListByStatus(o.GetLocalDB(), in.Status, in.EventID)
if err != nil {
return nil, err
}
return eventIds, nil
}
//通过状态 和 地址查询
func (o *oracle) Query_QueryEventIDsByAddrAndStatus(in *oty.QueryEventID) (types.Message, error) {
eventIds, err := getEventIDListByAddrAndStatus(o.GetLocalDB(), in.Addr, in.Status, in.EventID)
if err != nil {
return nil, err
}
return eventIds, nil
}
//通过类型和状态查询
func (o *oracle) Query_QueryEventIDsByTypeAndStatus(in *oty.QueryEventID) (types.Message, error) {
eventIds, err := getEventIDListByTypeAndStatus(o.GetLocalDB(), in.Type, in.Status, in.EventID)
if err != nil {
return nil, err
}
return eventIds, 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 oracle
import (
"github.com/33cn/chain33/pluginmgr"
"github.com/33cn/plugin/plugin/dapp/oracle/commands"
"github.com/33cn/plugin/plugin/dapp/oracle/executor"
"github.com/33cn/plugin/plugin/dapp/oracle/types"
)
func init() {
pluginmgr.Register(&pluginmgr.PluginBase{
Name: types.OracleX,
ExecName: executor.GetName(),
Exec: executor.Init,
Cmd: commands.OracleCmd,
//RPC: rpc.Init,
})
}
all:
sh ./create_protobuf.sh
#!/bin/sh
protoc --go_out=plugins=grpc:../types ./*.proto --proto_path=. --proto_path="../../../../vendor/github.com/33cn/chain33/types/proto/"
syntax = "proto3";
package types;
//事件
message OracleStatus {
string eventID = 1; //事件ID
string addr = 2; //发布者地址
string type = 3; //游戏类别
string subType = 4; //游戏子类别
int64 time = 5; //结果公布参考时间
string content = 6; //事件内容
string introduction = 7; //事件描述
EventStatus status = 8; //操作状态
string source = 9; //数据来源
string result = 10; //事件结果
EventStatus preStatus=11; //上次操作后状态及操作者地址
}
// action
message OracleAction {
oneof value {
EventPublish eventPublish = 1;
EventAbort eventAbort = 2;
ResultPrePublish resultPrePublish = 3;
ResultPublish resultPublish = 4;
ResultAbort resultAbort = 5;
}
int32 Ty = 7;
}
message EventStatus {
string opAddr = 1; //修改事件状态的地址
int32 status = 2; //事件状态
}
message EventPublish {
string type = 2; //游戏类别
string subType = 3; //游戏子类别
int64 time = 4; //结果公布参考时间
string content = 5; //事件内容
string introduction = 6; //事件描述
}
message EventAbort {
string eventID = 2; //发布事件的ID
}
message ResultPrePublish {
string eventID = 2; //发布事件的ID
string source = 3; //数据来源
string result = 4; //发布数据
}
message ResultPublish {
string eventID = 2; //发布事件的ID
string source = 3; //数据来源
string result = 4; //发布数据
}
message ResultAbort {
string eventID = 2; //发布事件的ID
}
// localDB
message EventRecord {
string eventID = 1; //发布的事件的ID
}
message QueryOracleInfos {
repeated string eventID = 1; //发布的事件的ID
}
message ReplyEventIDs {
repeated string eventID = 1; //发布事件的ID
}
message QueryEventID {
int32 status = 1; //事件状态
string addr = 2; //事件发布者的地址
string type = 3; //事件类型
string eventID = 4; //事件ID
}
message ReceiptOracle {
string eventID = 1; //发布事件ID
int32 status = 2; //事件状态
string addr = 3; //事件发布者的地址
string type = 4; //事件类型
int32 preStatus = 6;//事件的前一个状态
}
message ReplyOracleStatusList {
repeated OracleStatus status = 1; //状态集
}
\ No newline at end of file
/*
* Copyright Fuzamei Corp. 2018 All Rights Reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
package rpc_test
import (
"fmt"
"strings"
"testing"
"time"
"github.com/33cn/chain33/rpc/jsonclient"
rpctypes "github.com/33cn/chain33/rpc/types"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/util/testnode"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
commonlog "github.com/33cn/chain33/common/log"
_ "github.com/33cn/chain33/system"
_ "github.com/33cn/plugin/plugin"
oty "github.com/33cn/plugin/plugin/dapp/oracle/types"
)
func init() {
commonlog.SetLogLevel("error")
}
func TestJRPCChannel(t *testing.T) {
// 启动RPCmocker
mocker := testnode.New("--notset--", nil)
defer func() {
mocker.Close()
}()
mocker.Listen()
jrpcClient := mocker.GetJSONC()
assert.NotNil(t, jrpcClient)
testCases := []struct {
fn func(*testing.T, *jsonclient.JSONClient) error
}{
{fn: testPublishEventRawCmd},
{fn: testAbortEventRawTxCmd},
{fn: testPrePublishResultRawTxCmd},
{fn: testAbortPrePubResultRawTxCmd},
{fn: testPublishResultRawTxCmd},
}
for index, testCase := range testCases {
err := testCase.fn(t, jrpcClient)
if err == nil {
continue
}
assert.NotEqualf(t, err, types.ErrActionNotSupport, "test index %d", index)
if strings.Contains(err.Error(), "rpc: can't find") {
assert.FailNowf(t, err.Error(), "test index %d", index)
}
}
testCases = []struct {
fn func(*testing.T, *jsonclient.JSONClient) error
}{
{fn: testQueryOracleListByIDsRawTxCmd},
{fn: testQueryEventIDByAddrAndStatusRawTxCmd},
{fn: testQueryEventIDByTypeAndStatusRawTxCmd},
{fn: testQueryEventIDByStatusRawTxCmd},
}
result := []error{
oty.ErrParamNeedIDs,
oty.ErrParamStatusInvalid,
types.ErrNotFound,
types.ErrNotFound,
}
for index, testCase := range testCases {
err := testCase.fn(t, jrpcClient)
assert.Equal(t, result[index], err, fmt.Sprint(index))
}
}
func testPublishEventRawCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
timeStr := "2019-01-21 15:30:00"
layout := "2006-01-02 15:04:05"
ti, err := time.Parse(layout, timeStr)
if err != nil {
fmt.Printf("time error:%v\n", err.Error())
return errors.Errorf("time error:%v\n", err.Error())
}
payload := &oty.EventPublish{
Type: "football",
SubType: "Premier League",
Time: ti.Unix(),
Content: "{\"team1\":\"ChelSea\", \"team2\":\"Manchester\",\"resultType\":\"score\"}",
Introduction: "guess the sore result of football game between ChelSea and Manchester in 2019-01-21 14:00:00",
}
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(oty.OracleX),
ActionName: oty.CreateEventPublishTx,
Payload: types.MustPBToJSON(payload),
}
var res string
return jrpc.Call("Chain33.CreateTransaction", params, &res)
}
func testAbortEventRawTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
payload := &oty.EventAbort{EventID: "123"}
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(oty.OracleX),
ActionName: oty.CreateAbortEventPublishTx,
Payload: types.MustPBToJSON(payload),
}
var res string
return jrpc.Call("Chain33.CreateTransaction", params, &res)
}
func testPrePublishResultRawTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
payload := &oty.ResultPrePublish{
EventID: "123",
Source: "新浪体育",
Result: "{\"team1\":3, \"team2\":2}",
}
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(oty.OracleX),
ActionName: oty.CreatePrePublishResultTx,
Payload: types.MustPBToJSON(payload),
}
var res string
return jrpc.Call("Chain33.CreateTransaction", params, &res)
}
func testAbortPrePubResultRawTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
payload := &oty.EventAbort{EventID: "123"}
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(oty.OracleX),
ActionName: oty.CreateAbortResultPrePublishTx,
Payload: types.MustPBToJSON(payload),
}
var res string
return jrpc.Call("Chain33.CreateTransaction", params, &res)
}
func testPublishResultRawTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
payload := &oty.ResultPrePublish{
EventID: "123",
Source: "新浪体育",
Result: "{\"team1\":3, \"team2\":2}",
}
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(oty.OracleX),
ActionName: oty.CreateResultPublishTx,
Payload: types.MustPBToJSON(payload),
}
var res string
return jrpc.Call("Chain33.CreateTransaction", params, &res)
}
func testQueryOracleListByIDsRawTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{}
var params rpctypes.Query4Jrpc
req := &oty.QueryOracleInfos{}
params.Execer = oty.OracleX
params.FuncName = oty.FuncNameQueryOracleListByIDs
params.Payload = types.MustPBToJSON(req)
rep = &oty.ReplyOracleStatusList{}
return jrpc.Call("Chain33.Query", params, rep)
}
func testQueryEventIDByAddrAndStatusRawTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{}
var params rpctypes.Query4Jrpc
req := &oty.QueryEventID{}
params.Execer = oty.OracleX
params.FuncName = oty.FuncNameQueryEventIDByAddrAndStatus
params.Payload = types.MustPBToJSON(req)
rep = &oty.ReplyEventIDs{}
return jrpc.Call("Chain33.Query", params, rep)
}
func testQueryEventIDByTypeAndStatusRawTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{}
var params rpctypes.Query4Jrpc
req := &oty.QueryEventID{
Type: "football",
Status: 1,
Addr: "",
}
params.Execer = oty.OracleX
params.FuncName = oty.FuncNameQueryEventIDByTypeAndStatus
params.Payload = types.MustPBToJSON(req)
rep = &oty.ReplyEventIDs{}
return jrpc.Call("Chain33.Query", params, rep)
}
func testQueryEventIDByStatusRawTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{}
var params rpctypes.Query4Jrpc
req := &oty.QueryEventID{
Status: 1,
Type: "",
Addr: "",
}
params.Execer = oty.OracleX
params.FuncName = oty.FuncNameQueryEventIDByStatus
params.Payload = types.MustPBToJSON(req)
rep = &oty.ReplyEventIDs{}
return jrpc.Call("Chain33.Query", params, rep)
}
This diff is collapsed.
/*
* 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 types
import "errors"
var (
// OracleX oracle name
OracleX = "oracle"
)
// oracle action type
const (
ActionEventPublish = iota + 1 //事件发布
ActionResultPrePublish
ActionResultPublish
ActionEventAbort
ActionResultAbort
)
// oracle status
const (
NoEvent = iota
EventPublished
EventAborted
ResultPrePublished
ResultAborted
ResultPublished
)
// log type define
const (
TyLogEventPublish = 810
TyLogEventAbort = 811
TyLogResultPrePublish = 812
TyLogResultAbort = 813
TyLogResultPublish = 814
)
// executor action and function define
const (
// FuncNameQueryOracleListByIDs 根据ids查询OracleStatus
FuncNameQueryOracleListByIDs = "QueryOraclesByIDs"
// FuncNameQueryEventIDByStatus 根据状态查询eventID
FuncNameQueryEventIDByStatus = "QueryEventIDsByStatus"
// FuncNameQueryEventIDByAddrAndStatus 根据创建者地址和状态查询eventID
FuncNameQueryEventIDByAddrAndStatus = "QueryEventIDsByAddrAndStatus"
// FuncNameQueryEventIDByTypeAndStatus 根据事件类型和状态查询eventID
FuncNameQueryEventIDByTypeAndStatus = "QueryEventIDsByTypeAndStatus"
// CreateEventPublishTx 创建发布事件交易
CreateEventPublishTx = "EventPublish"
// CreateAbortEventPublishTx 创建取消发布事件交易
CreateAbortEventPublishTx = "EventAbort"
// CreatePrePublishResultTx 创建预发布事件结果交易
CreatePrePublishResultTx = "ResultPrePublish"
// CreateAbortResultPrePublishTx 创建取消预发布的事件结果交易
CreateAbortResultPrePublishTx = "ResultAbort"
// CreateResultPublishTx 创建预发布事件结果交易
CreateResultPublishTx = "ResultPublish"
)
// query param define
const (
// ListDESC 降序
ListDESC = int32(0)
// DefaultCount 默认一次取多少条记录
DefaultCount = int32(20)
)
// Errors for oracle
var (
ErrTimeMustBeFuture = errors.New("ErrTimeMustBeFuture")
ErrNoPrivilege = errors.New("ErrNoPrivilege")
ErrOracleRepeatHash = errors.New("ErrOracleRepeatHash")
ErrEventIDNotFound = errors.New("ErrEventIDNotFound")
ErrEventAbortNotAllowed = errors.New("ErrEventAbortNotAllowed")
ErrResultPrePublishNotAllowed = errors.New("ErrResultPrePublishNotAllowed")
ErrPrePublishAbortNotAllowed = errors.New("ErrPrePublishAbortNotAllowed")
ErrResultPublishNotAllowed = errors.New("ErrResultPublishNotAllowed")
ErrParamNeedIDs = errors.New("ErrParamNeedIDs")
ErrParamStatusInvalid = errors.New("ErrParamStatusInvalid")
ErrParamAddressMustnotEmpty = errors.New("ErrParamAddressMustnotEmpty")
ErrParamTypeMustNotEmpty = errors.New("ErrParamTypeMustNotEmpty")
)
This diff is collapsed.
package types
import (
"fmt"
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/common/db/table"
"github.com/33cn/chain33/types"
)
/*
table struct
data: oracle
index: addr,status,index,type
*/
var opt = &table.Option{
Prefix: "LODB",
Name: "oracle",
Primary: "eventid",
Index: []string{"status", "addr_status", "type_status"},
}
//NewTable 新建表
func NewTable(kvdb db.KV) *table.Table {
rowmeta := NewOracleRow()
table, err := table.NewTable(rowmeta, kvdb, opt)
if err != nil {
panic(err)
}
return table
}
//OracleRow table meta 结构
type OracleRow struct {
*ReceiptOracle
}
//NewOracleRow 新建一个meta 结构
func NewOracleRow() *OracleRow {
return &OracleRow{ReceiptOracle: &ReceiptOracle{}}
}
//CreateRow 新建数据行(注意index 数据一定也要保存到数据中,不能就保存eventid)
func (tx *OracleRow) CreateRow() *table.Row {
return &table.Row{Data: &ReceiptOracle{}}
}
//SetPayload 设置数据
func (tx *OracleRow) SetPayload(data types.Message) error {
if txdata, ok := data.(*ReceiptOracle); ok {
tx.ReceiptOracle = txdata
return nil
}
return types.ErrTypeAsset
}
//Get 按照indexName 查询 indexValue
func (tx *OracleRow) Get(key string) ([]byte, error) {
if key == "eventid" {
return []byte(tx.EventID), nil
} else if key == "status" {
return []byte(fmt.Sprintf("%2d", tx.Status)), nil
} else if key == "addr_status" {
return []byte(fmt.Sprintf("%s:%2d", tx.Addr, tx.Status)), nil
} else if key == "type_status" {
return []byte(fmt.Sprintf("%s:%2d", tx.Type, tx.Status)), nil
}
return nil, types.ErrNotFound
}
/*
* 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 types
import (
"reflect"
"github.com/33cn/chain33/types"
)
func init() {
// init executor type
types.AllowUserExec = append(types.AllowUserExec, []byte(OracleX))
types.RegistorExecutor(OracleX, NewType())
types.RegisterDappFork(OracleX, "Enable", 0)
}
// OracleType 预言机执行器类型
type OracleType struct {
types.ExecTypeBase
}
// NewType 创建执行器类型
func NewType() *OracleType {
c := &OracleType{}
c.SetChild(c)
return c
}
// GetName 获取执行器名称
func (o *OracleType) GetName() string {
return OracleX
}
// GetPayload 获取oracle action
func (o *OracleType) GetPayload() types.Message {
return &OracleAction{}
}
// GetTypeMap 获取类型map
func (o *OracleType) GetTypeMap() map[string]int32 {
return map[string]int32{
"EventPublish": ActionEventPublish,
"EventAbort": ActionEventAbort,
"ResultPrePublish": ActionResultPrePublish,
"ResultAbort": ActionResultAbort,
"ResultPublish": ActionResultPublish,
}
}
// GetLogMap 获取日志map
func (o *OracleType) GetLogMap() map[int64]*types.LogInfo {
return map[int64]*types.LogInfo{
TyLogEventPublish: {Ty: reflect.TypeOf(ReceiptOracle{}), Name: "LogEventPublish"},
TyLogEventAbort: {Ty: reflect.TypeOf(ReceiptOracle{}), Name: "LogEventAbort"},
TyLogResultPrePublish: {Ty: reflect.TypeOf(ReceiptOracle{}), Name: "LogResultPrePublish"},
TyLogResultAbort: {Ty: reflect.TypeOf(ReceiptOracle{}), Name: "LogResultAbort"},
TyLogResultPublish: {Ty: reflect.TypeOf(ReceiptOracle{}), Name: "LogResultPublish"},
}
}
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