Unverified Commit 748d60d9 authored by vipwzw's avatar vipwzw Committed by GitHub

Merge pull request #105 from linj-disanbo/exec_unfreeze

Exec unfreeze
parents 4914e587 74c4a650
...@@ -16,5 +16,6 @@ import ( ...@@ -16,5 +16,6 @@ import (
_ "github.com/33cn/plugin/plugin/dapp/ticket" //auto gen _ "github.com/33cn/plugin/plugin/dapp/ticket" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/token" //auto gen _ "github.com/33cn/plugin/plugin/dapp/token" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/trade" //auto gen _ "github.com/33cn/plugin/plugin/dapp/trade" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/unfreeze" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/valnode" //auto gen _ "github.com/33cn/plugin/plugin/dapp/valnode" //auto gen
) )
all:
chmod +x ./build.sh
./build.sh $(OUT) $(FLAG)
\ No newline at end of file
#!/usr/bin/env bash
output_dir=${1}
strpwd=$(pwd)
strcmd=${strpwd##*dapp/}
strapp=${strcmd%/cmd*}
OUT_DIR="${output_dir}/$strapp"
[ ! -e "${OUT_DIR}" ] && mkdir -p "${OUT_DIR}"
# shellcheck disable=SC2086
cp ./build/* "${OUT_DIR}"
#!/usr/bin/env bash
CLI="docker exec ${NODE3} /root/chain33-cli"
beneficiary=12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv
beneficiary_key=0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01
#owner=14KEKbYtKKQm4wMthSK9J4La4nAiidGozt
owner_key=CC38546E9E659D15E6B4893F0AB32A06D103931A8230B0BDE71459D2B27D6944
unfreeze_exec_addr=15YsqAuXeEXVHgm6RVx4oJaAAnhtwqnu3H
function unfreeze_test() {
echo "=========== # unfreeze test ============="
echo "=== 1 check exec addr"
result=$($CLI exec addr -e unfreeze)
if [ "${result}" != "${unfreeze_exec_addr}" ]; then
echo "unfreeze exec addr is not right, expect ${unfreeze_exec_addr} result ${result}"
exit 1
fi
block_wait "${CLI}" 2
echo "=== 2 prepare: transfer bty to unfreeze "
result=$($CLI send coins transfer -a 5 -n test -t ${unfreeze_exec_addr} -k ${owner_key})
echo "${result}"
block_wait "${CLI}" 2
echo "=== 3 create unfreeze tx"
tx_hash=$(${CLI} send unfreeze create fix_amount -a 0.01 -e coins -s bty -b ${beneficiary} -p 20 -t 2 -k ${owner_key})
block_wait "${CLI}" 2
unfreeze_id=$(${CLI} tx query -s "${tx_hash}" | jq ".receipt.logs[2].log.current.unfreezeID")
unfreeze_id2=${unfreeze_id#\"}
uid=${unfreeze_id2%\"}
echo "==== 4 check some message "
sleep 20
withdraw=$(${CLI} unfreeze show_withdraw --id "${uid}" | jq ".availableAmount")
if [ "${withdraw}" = "0" ]; then
echo "create unfreeze failed, expect withdraw shoult >0 "
exit 1
fi
echo "==== 5 withdraw"
${CLI} send unfreeze withdraw --id "${uid}" -k "${beneficiary_key}"
block_wait "${CLI}" 2
remaining=$(${CLI} unfreeze show --id "${uid}" | jq ".remaining")
if [ "${remaining}" = '"200000000"' ]; then
echo "withdraw failed, expect remaining < 200000000, result ${remaining}"
exit 1
fi
echo "==== 6 termenate"
${CLI} send unfreeze terminate --id "${uid}" -k "${owner_key}"
block_wait "${CLI}" 2
remaining=$(${CLI} unfreeze show --id "${uid}" | jq ".remaining")
if [ "${remaining}" != '"0"' ]; then
echo "terminate failed, expect remaining 0, result ${remaining}"
exit 1
fi
echo "==================== unfreeze test end"
}
function unfreeze() {
if [ "${2}" == "init" ]; then
return
elif [ "${2}" == "config" ]; then
return
elif [ "${2}" == "test" ]; then
unfreeze_test "${1}"
fi
}
// 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 (
"bytes"
"encoding/hex"
"encoding/json"
"fmt"
"math"
"os"
"strings"
"github.com/33cn/chain33/rpc/jsonclient"
rpctypes "github.com/33cn/chain33/rpc/types"
"github.com/spf13/cobra"
"github.com/33cn/chain33/types"
pty "github.com/33cn/plugin/plugin/dapp/unfreeze/types"
)
// Cmd unfreeze 客户端主程序
func Cmd() *cobra.Command {
cmd := &cobra.Command{
Use: "unfreeze",
Short: "Unfreeze construct management",
Args: cobra.MinimumNArgs(1),
}
cmd.AddCommand(createCmd())
cmd.AddCommand(withdrawCmd())
cmd.AddCommand(terminateCmd())
cmd.AddCommand(showCmd())
cmd.AddCommand(queryWithdrawCmd())
return cmd
}
func createCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "create",
Short: "create unfreeze construct",
}
cmd.AddCommand(fixAmountCmd())
cmd.AddCommand(leftCmd())
return cmd
}
func createFlag(cmd *cobra.Command) *cobra.Command {
cmd.PersistentFlags().StringP("beneficiary", "b", "", "address of beneficiary")
cmd.MarkFlagRequired("beneficiary")
cmd.PersistentFlags().StringP("asset_exec", "e", "", "asset exec")
cmd.MarkFlagRequired("asset_exec")
cmd.PersistentFlags().StringP("asset_symbol", "s", "", "asset symbol")
cmd.MarkFlagRequired("asset_symbol")
cmd.PersistentFlags().Float64P("total", "t", 0, "total count of asset")
cmd.MarkFlagRequired("total")
cmd.PersistentFlags().Int64P("start_ts", "", 0, "effect, UTC timestamp")
//cmd.MarkFlagRequired("start_ts")
return cmd
}
func checkAmount(amount float64) error {
if amount < 0 || amount > float64(types.MaxCoin/types.Coin) {
return types.ErrAmount
}
return nil
}
func getCreateFlags(cmd *cobra.Command) (*pty.UnfreezeCreate, error) {
beneficiary, _ := cmd.Flags().GetString("beneficiary")
exec, _ := cmd.Flags().GetString("asset_exec")
symbol, _ := cmd.Flags().GetString("asset_symbol")
total, _ := cmd.Flags().GetFloat64("total")
startTs, _ := cmd.Flags().GetInt64("start_ts")
if err := checkAmount(total); err != nil {
return nil, types.ErrAmount
}
totalInt64 := int64(math.Trunc((total+0.0000001)*1e4)) * 1e4
unfreeze := &pty.UnfreezeCreate{
StartTime: startTs,
AssetExec: exec,
AssetSymbol: symbol,
TotalCount: totalInt64,
Beneficiary: beneficiary,
Means: "",
}
return unfreeze, nil
}
func fixAmountCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "fix_amount",
Short: "create fix amount means unfreeze construct",
Run: fixAmount,
}
cmd = createFlag(cmd)
cmd.Flags().Float64P("amount", "a", 0, "amount every period")
cmd.MarkFlagRequired("amount")
cmd.Flags().Int64P("period", "p", 0, "period in second")
cmd.MarkFlagRequired("period")
return cmd
}
func fixAmount(cmd *cobra.Command, args []string) {
create, err := getCreateFlags(cmd)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
amount, _ := cmd.Flags().GetFloat64("amount")
if err = checkAmount(amount); err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
amountInt64 := int64(math.Trunc((amount+0.0000001)*1e4)) * 1e4
period, _ := cmd.Flags().GetInt64("period")
create.Means = pty.FixAmountX
create.MeansOpt = &pty.UnfreezeCreate_FixAmount{FixAmount: &pty.FixAmount{Period: period, Amount: amountInt64}}
paraName, _ := cmd.Flags().GetString("paraName")
tx, err := pty.CreateUnfreezeCreateTx(paraName, create)
if err != nil {
fmt.Printf("Create Tx frailed: %s", err)
return
}
outputTx(tx)
}
func outputTx(tx *types.Transaction) {
txHex := types.Encode(tx)
fmt.Println(hex.EncodeToString(txHex))
}
func leftCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "left_proportion",
Short: "create left proportion means unfreeze construct",
Run: left,
}
cmd = createFlag(cmd)
cmd.Flags().Int64P("ten_thousandth", "", 0, "input/10000 of total")
cmd.MarkFlagRequired("amount")
cmd.Flags().Int64P("period", "p", 0, "period in second")
cmd.MarkFlagRequired("period")
return cmd
}
func left(cmd *cobra.Command, args []string) {
create, err := getCreateFlags(cmd)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
tenThousandth, _ := cmd.Flags().GetInt64("ten_thousandth")
period, _ := cmd.Flags().GetInt64("period")
create.Means = pty.FixAmountX
create.MeansOpt = &pty.UnfreezeCreate_LeftProportion{
LeftProportion: &pty.LeftProportion{Period: period, TenThousandth: tenThousandth}}
paraName, _ := cmd.Flags().GetString("paraName")
tx, err := pty.CreateUnfreezeCreateTx(paraName, create)
if err != nil {
fmt.Printf("Create Tx frailed: %s", err)
return
}
outputTx(tx)
}
func withdrawCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "withdraw",
Short: "withdraw asset from construct",
Run: withdraw,
}
cmd.Flags().StringP("id", "", "", "unfreeze construct id")
cmd.MarkFlagRequired("id")
return cmd
}
func terminateCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "terminate",
Short: "terminate construct",
Run: terminate,
}
cmd.Flags().StringP("id", "", "", "unfreeze construct id")
cmd.MarkFlagRequired("id")
return cmd
}
func showCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "show",
Short: "show construct",
Run: show,
}
cmd.Flags().StringP("id", "", "", "unfreeze construct id")
cmd.MarkFlagRequired("id")
return cmd
}
func queryWithdrawCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "show_withdraw",
Short: "show available withdraw amount of one unfreeze construct",
Run: queryWithdraw,
}
cmd.Flags().StringP("id", "", "", "unfreeze construct id")
cmd.MarkFlagRequired("id")
return cmd
}
func withdraw(cmd *cobra.Command, args []string) {
id, _ := cmd.Flags().GetString("id")
paraName, _ := cmd.Flags().GetString("paraName")
tx, err := pty.CreateUnfreezeWithdrawTx(paraName, &pty.UnfreezeWithdraw{UnfreezeID: id})
if err != nil {
fmt.Printf("Create Tx frailed: %s", err)
return
}
outputTx(tx)
}
func terminate(cmd *cobra.Command, args []string) {
id, _ := cmd.Flags().GetString("id")
paraName, _ := cmd.Flags().GetString("paraName")
tx, err := pty.CreateUnfreezeTerminateTx(paraName, &pty.UnfreezeTerminate{UnfreezeID: id})
if err != nil {
fmt.Printf("Create Tx frailed: %s", err)
return
}
outputTx(tx)
}
func queryWithdraw(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
paraName, _ := cmd.Flags().GetString("paraName")
id, _ := cmd.Flags().GetString("id")
cli, err := jsonclient.NewJSONClient(rpcLaddr)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
param := &rpctypes.Query4Jrpc{
Execer: getRealExecName(paraName, pty.UnfreezeX),
FuncName: "GetUnfreezeWithdraw",
Payload: types.MustPBToJSON(&types.ReqString{Data: id}),
}
var resp pty.ReplyQueryUnfreezeWithdraw
err = cli.Call("Chain33.Query", param, &resp)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
jsonOutput(&resp)
}
func show(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
paraName, _ := cmd.Flags().GetString("paraName")
id, _ := cmd.Flags().GetString("id")
cli, err := jsonclient.NewJSONClient(rpcLaddr)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
param := &rpctypes.Query4Jrpc{
Execer: getRealExecName(paraName, pty.UnfreezeX),
FuncName: "GetUnfreeze",
Payload: types.MustPBToJSON(&types.ReqString{Data: id}),
}
var resp pty.Unfreeze
err = cli.Call("Chain33.Query", param, &resp)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
jsonOutput(&resp)
}
func getRealExecName(paraName string, name string) string {
if strings.HasPrefix(name, "user.p.") {
return name
}
return paraName + name
}
func jsonOutput(resp types.Message) {
data, err := types.PBToJSON(resp)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
var buf bytes.Buffer
err = json.Indent(&buf, data, "", " ")
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
fmt.Println(buf.String())
}
// 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 unfreeze 提供了定期解冻合约的实现
// 功能描述:定期解冻合约帮助用户锁定一定量的币, 按在指定的规制解冻给受益人,
// 适用于分期付款, 分期支付形式的员工激励等情景。
//
// 合约提供了3类操作
// 1. 创建定期解冻合约:创建时需要指定支付的资产和总量,以及定期解冻的形式。
// 1. 受益人提币:受益人提走解冻了的资产。
// 1. 发起人终止合约: 发起人可以终止合约的履行。
//
// 解冻的形式目前支持两种
// 1. 固定数额解冻:指定时间间隔,解冻固定的资产。
// 1. 按剩余量的固定比例解冻:指定时间间隔,按剩余量的固定比例解冻。 这种方式,越到后面解冻的越少。
// 说明:在合约创建时, 就可以解冻一次。
// 举例, 一个固定数额解冻和合约, 总量为100, 一个月解冻10. 创建时可以由受益人提走10, 第一个月后又可以提走10.
// 在受益人没有及时提币的情况下, 受益人在一段时间之后可以一次性提走本该解冻的所有的币。 即解冻的币是按指定
// 形式解冻的,和受益人的提币时间和次数等都不会影响解冻的进程。
package unfreeze
// 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
// 定期解冻token
// 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/account"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
pty "github.com/33cn/plugin/plugin/dapp/unfreeze/types"
)
// Exec_Create 执行创建冻结合约
func (u *Unfreeze) Exec_Create(payload *pty.UnfreezeCreate, tx *types.Transaction, index int) (*types.Receipt, error) {
if payload.AssetExec == "" || payload.AssetSymbol == "" || payload.TotalCount <= 0 || payload.Means == "" {
return nil, types.ErrInvalidParam
}
unfreeze, err := u.newEntity(payload, tx)
if err != nil {
uflog.Error("unfreeze create entity", "addr", tx.From(), "payload", payload)
return nil, err
}
receipt1, err := u.create(unfreeze)
if err != nil {
uflog.Error("unfreeze create order", "addr", tx.From(), "unfreeze", unfreeze)
return nil, err
}
acc, err := account.NewAccountDB(payload.AssetExec, payload.AssetSymbol, u.GetStateDB())
if err != nil {
uflog.Error("unfreeze create new account", "addr", tx.From(), "execAddr",
dapp.ExecAddress(string(tx.Execer)), "exec", payload.AssetExec, "symbol", payload.AssetSymbol)
return nil, err
}
receipt, err := acc.ExecFrozen(unfreeze.Initiator, dapp.ExecAddress(string(tx.Execer)), payload.TotalCount)
if err != nil {
uflog.Error("unfreeze create exec frozen", "addr", tx.From(), "execAddr", dapp.ExecAddress(string(tx.Execer)),
"ExecFrozen amount", payload.TotalCount, "exec", payload.AssetExec, "symbol", payload.AssetSymbol)
return nil, err
}
return mergeReceipt(receipt, receipt1)
}
// Exec_Withdraw 执行冻结合约中提币
func (u *Unfreeze) Exec_Withdraw(payload *pty.UnfreezeWithdraw, tx *types.Transaction, index int) (*types.Receipt, error) {
unfreeze, err := loadUnfreeze(payload.UnfreezeID, u.GetStateDB())
if err != nil {
return nil, err
}
if unfreeze.Beneficiary != tx.From() {
uflog.Error("unfreeze withdraw no privilege", "beneficiary", unfreeze.Beneficiary, "txFrom", tx.From())
return nil, pty.ErrNoPrivilege
}
if unfreeze.Remaining <= 0 {
uflog.Error("unfreeze withdraw no asset")
return nil, pty.ErrUnfreezeEmptied
}
amount, receipt1, err := u.withdraw(unfreeze)
if err != nil {
uflog.Error("unfreeze withdraw withdraw", "err", err, "unfreeze", unfreeze)
return nil, err
}
acc, err := account.NewAccountDB(unfreeze.AssetExec, unfreeze.AssetSymbol, u.GetStateDB())
if err != nil {
return nil, err
}
execAddr := dapp.ExecAddress(string(tx.Execer))
receipt, err := acc.ExecTransferFrozen(unfreeze.Initiator, tx.From(), execAddr, amount)
if err != nil {
uflog.Error("unfreeze withdraw transfer", "execaddr", execAddr, "err", err, "from", unfreeze.Initiator,
"remain", unfreeze.Remaining, "withdraw", amount)
return nil, err
}
return mergeReceipt(receipt, receipt1)
}
// Exec_Terminate 执行终止冻结合约
func (u *Unfreeze) Exec_Terminate(payload *pty.UnfreezeTerminate, tx *types.Transaction, index int) (*types.Receipt, error) {
unfreeze, err := loadUnfreeze(payload.UnfreezeID, u.GetStateDB())
if err != nil {
return nil, err
}
if tx.From() != unfreeze.Initiator {
uflog.Error("unfreeze terminate no privilege", "err", pty.ErrUnfreezeID, "initiator",
unfreeze.Initiator, "from", tx.From())
return nil, pty.ErrNoPrivilege
}
amount, receipt1, err := u.terminator(unfreeze)
if err != nil {
uflog.Error("unfreeze terminate ", "err", err, "unfreeze", unfreeze)
return nil, err
}
acc, err := account.NewAccountDB(unfreeze.AssetExec, unfreeze.AssetSymbol, u.GetStateDB())
if err != nil {
return nil, err
}
execAddr := dapp.ExecAddress(string(tx.Execer))
receipt, err := acc.ExecActive(unfreeze.Initiator, execAddr, amount)
if err != nil {
uflog.Error("unfreeze terminate ", "addr", unfreeze.Initiator, "execaddr", execAddr, "err", err)
return nil, err
}
return mergeReceipt(receipt, receipt1)
}
func (u *Unfreeze) newEntity(payload *pty.UnfreezeCreate, tx *types.Transaction) (*pty.Unfreeze, error) {
id := unfreezeID(tx.Hash())
unfreeze := &pty.Unfreeze{
UnfreezeID: string(id),
StartTime: payload.StartTime,
AssetExec: payload.AssetExec,
AssetSymbol: payload.AssetSymbol,
TotalCount: payload.TotalCount,
Remaining: payload.TotalCount,
Initiator: tx.From(),
Beneficiary: payload.Beneficiary,
Means: payload.Means,
}
if unfreeze.StartTime == 0 {
unfreeze.StartTime = u.GetBlockTime()
}
means, err := newMeans(payload.Means)
if err != nil {
return nil, err
}
unfreeze, err = means.setOpt(unfreeze, payload)
if err != nil {
return nil, err
}
return unfreeze, nil
}
// 创建解冻状态
func (u *Unfreeze) create(unfreeze *pty.Unfreeze) (*types.Receipt, error) {
k := []byte(unfreeze.UnfreezeID)
v := types.Encode(unfreeze)
err := u.GetStateDB().Set(k, v)
if err != nil {
return nil, err
}
receiptLog := getUnfreezeLog(nil, unfreeze)
return &types.Receipt{Ty: types.ExecOk,
KV: []*types.KeyValue{{Key: k, Value: v}}, Logs: []*types.ReceiptLog{receiptLog}}, nil
}
func mergeReceipt(r1 *types.Receipt, r2 *types.Receipt) (*types.Receipt, error) {
r1.Logs = append(r1.Logs, r2.Logs...)
r1.KV = append(r1.KV, r2.KV...)
r1.Ty = types.ExecOk
return r1, nil
}
func getUnfreezeLog(prev, cur *pty.Unfreeze) *types.ReceiptLog {
log := &types.ReceiptLog{}
log.Ty = pty.TyLogCreateUnfreeze
r := &pty.ReceiptUnfreeze{Prev: prev, Current: cur}
log.Log = types.Encode(r)
return log
}
// 提取解冻币
func (u *Unfreeze) withdraw(unfreeze *pty.Unfreeze) (int64, *types.Receipt, error) {
means, err := newMeans(unfreeze.Means)
if err != nil {
return 0, nil, err
}
frozen, err := means.calcFrozen(unfreeze, u.GetBlockTime())
if err != nil {
return 0, nil, err
}
unfreezeOld := *unfreeze
unfreeze, amount := withdraw(unfreeze, frozen)
receiptLog := getUnfreezeLog(&unfreezeOld, unfreeze)
k := []byte(unfreeze.UnfreezeID)
v := types.Encode(unfreeze)
err = u.GetStateDB().Set(k, v)
if err != nil {
return 0, nil, err
}
return amount, &types.Receipt{Ty: types.ExecOk, KV: []*types.KeyValue{{Key: k, Value: v}},
Logs: []*types.ReceiptLog{receiptLog}}, nil
}
// 中止定期解冻
func (u *Unfreeze) terminator(unfreeze *pty.Unfreeze) (int64, *types.Receipt, error) {
if unfreeze.Remaining <= 0 {
return 0, nil, pty.ErrUnfreezeEmptied
}
unfreezeOld := *unfreeze
amount := unfreeze.Remaining
unfreeze.Remaining = 0
receiptLog := getUnfreezeLog(&unfreezeOld, unfreeze)
k := []byte(unfreeze.UnfreezeID)
v := types.Encode(unfreeze)
err := u.GetStateDB().Set(k, v)
if err != nil {
return 0, nil, err
}
return amount, &types.Receipt{Ty: types.ExecOk, KV: []*types.KeyValue{{Key: k, Value: v}},
Logs: []*types.ReceiptLog{receiptLog}}, nil
}
func loadUnfreeze(id string, db dbm.KV) (*pty.Unfreeze, error) {
value, err := db.Get([]byte(id))
if err != nil {
uflog.Error("unfreeze terminate get", "id", id, "err", err)
return nil, err
}
var unfreeze pty.Unfreeze
err = types.Decode(value, &unfreeze)
if err != nil {
uflog.Error("unfreeze terminate decode", "err", err)
return nil, err
}
return &unfreeze, 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 executor
import (
"github.com/33cn/chain33/types"
uf "github.com/33cn/plugin/plugin/dapp/unfreeze/types"
)
func (u *Unfreeze) execDelLocal(receiptData *types.ReceiptData) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
if receiptData.GetTy() != types.ExecOk {
return dbSet, nil
}
for _, log := range receiptData.Logs {
switch log.Ty {
case uf.TyLogCreateUnfreeze, uf.TyLogWithdrawUnfreeze, uf.TyLogTerminateUnfreeze:
var receipt uf.ReceiptUnfreeze
err := types.Decode(log.Log, &receipt)
if err != nil {
return nil, err
}
kv := u.rollbackUnfreezeCreate(&receipt)
dbSet.KV = append(dbSet.KV, kv...)
}
}
return dbSet, nil
}
// ExecDelLocal_Create 本地撤销执行创建冻结合约
func (u *Unfreeze) ExecDelLocal_Create(payload *uf.UnfreezeCreate, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return u.execDelLocal(receiptData)
}
// ExecDelLocal_Withdraw 本地撤销执行冻结合约中提币
func (u *Unfreeze) ExecDelLocal_Withdraw(payload *uf.UnfreezeWithdraw, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return u.execDelLocal(receiptData)
}
// ExecDelLocal_Terminate 本地撤销执行冻结合约的终止
func (u *Unfreeze) ExecDelLocal_Terminate(payload *uf.UnfreezeTerminate, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return u.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"
uf "github.com/33cn/plugin/plugin/dapp/unfreeze/types"
)
func (u *Unfreeze) execLocal(receiptData *types.ReceiptData) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
if receiptData.GetTy() != types.ExecOk {
return dbSet, nil
}
for _, log := range receiptData.Logs {
switch log.Ty {
case uf.TyLogCreateUnfreeze, uf.TyLogWithdrawUnfreeze, uf.TyLogTerminateUnfreeze:
var receipt uf.ReceiptUnfreeze
err := types.Decode(log.Log, &receipt)
if err != nil {
return nil, err
}
kv := u.saveUnfreezeCreate(&receipt)
dbSet.KV = append(dbSet.KV, kv...)
default:
}
}
return dbSet, nil
}
// ExecLocal_Create 本地执行创建冻结合约
func (u *Unfreeze) ExecLocal_Create(payload *uf.UnfreezeCreate, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return u.execLocal(receiptData)
}
// ExecLocal_Withdraw 本地执行提币
func (u *Unfreeze) ExecLocal_Withdraw(payload *uf.UnfreezeWithdraw, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return u.execLocal(receiptData)
}
// ExecLocal_Terminate 本地执行终止冻结合约
func (u *Unfreeze) ExecLocal_Terminate(payload *uf.UnfreezeTerminate, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return u.execLocal(receiptData)
}
func localKeys(res *uf.ReceiptUnfreeze, value []byte) (kvs []*types.KeyValue) {
kvs = append(kvs, &types.KeyValue{Key: initKey(res.Current.Initiator), Value: value})
kvs = append(kvs, &types.KeyValue{Key: beneficiaryKey(res.Current.Beneficiary), Value: value})
return
}
func (u *Unfreeze) saveUnfreezeCreate(res *uf.ReceiptUnfreeze) (kvs []*types.KeyValue) {
kvs = localKeys(res, []byte(res.Current.UnfreezeID))
return
}
func (u *Unfreeze) rollbackUnfreezeCreate(res *uf.ReceiptUnfreeze) (kvs []*types.KeyValue) {
kvs = localKeys(res, nil)
return
}
// 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 (
"testing"
"github.com/stretchr/testify/assert"
"github.com/33cn/chain33/account"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/common/crypto"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
pty "github.com/33cn/plugin/plugin/dapp/unfreeze/types"
)
type execEnv struct {
blockTime int64
blockHeight int64
difficulty uint64
}
var (
Symbol = "TEST"
AssetExecToken = "token"
AssetExecPara = "paracross"
PrivKeyA = "0x6da92a632ab7deb67d38c0f6560bcfed28167998f6496db64c258d5e8393a81b" // 1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4
PrivKeyB = "0x19c069234f9d3e61135fefbeb7791b149cdf6af536f26bebb310d4cd22c3fee4" // 1JRNjdEqp4LJ5fqycUBm9ayCKSeeskgMKR
PrivKeyC = "0x7a80a1f75d7360c6123c32a78ecf978c1ac55636f87892df38d8b85a9aeff115" // 1NLHPEcbTWWxxU3dGUZBhayjrCHD3psX7k
PrivKeyD = "0xcacb1f5d51700aea07fca2246ab43b0917d70405c65edea9b5063d72eb5c6b71" // 1MCftFynyvG2F4ED5mdHYgziDxx6vDrScs
Nodes = [][]byte{
[]byte("1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4"),
[]byte("1JRNjdEqp4LJ5fqycUBm9ayCKSeeskgMKR"),
[]byte("1NLHPEcbTWWxxU3dGUZBhayjrCHD3psX7k"),
[]byte("1MCftFynyvG2F4ED5mdHYgziDxx6vDrScs"),
}
)
func TestUnfreeze(t *testing.T) {
total := int64(100000)
accountA := types.Account{
Balance: total,
Frozen: 0,
Addr: string(Nodes[0]),
}
accountB := types.Account{
Balance: total,
Frozen: 0,
Addr: string(Nodes[1]),
}
execAddr := address.ExecAddress(pty.UnfreezeX)
stateDB, _ := dbm.NewGoMemDB("1", "2", 100)
accA, _ := account.NewAccountDB(AssetExecPara, Symbol, stateDB)
accA.SaveExecAccount(execAddr, &accountA)
accB, _ := account.NewAccountDB(AssetExecPara, Symbol, stateDB)
accB.SaveExecAccount(execAddr, &accountB)
env := execEnv{
10,
2,
1539918074,
}
ty := pty.UnfreezeType{}
// 创建
opt := &pty.FixAmount{Period: 10, Amount: 2}
p1 := &pty.UnfreezeCreate{
StartTime: 10,
AssetExec: AssetExecPara,
AssetSymbol: Symbol,
TotalCount: 10000,
Beneficiary: string(Nodes[1]),
Means: "FixAmount",
MeansOpt: &pty.UnfreezeCreate_FixAmount{FixAmount: opt},
}
createTx, err := ty.RPC_UnfreezeCreateTx(p1)
if err != nil {
t.Error("RPC_UnfreezeCreateTx", "err", err)
}
createTx, err = signTx(createTx, PrivKeyA)
if err != nil {
t.Error("RPC_UnfreezeCreateTx sign", "err", err)
}
exec := newUnfreeze()
exec.SetStateDB(stateDB)
exec.SetEnv(env.blockHeight, env.blockTime, env.difficulty)
receipt, err := exec.Exec(createTx, int(1))
assert.Nil(t, err)
assert.NotNil(t, receipt)
//t.Log(receipt)
accTmp := accA.LoadExecAccount(accountA.Addr, execAddr)
assert.Equal(t, total-p1.TotalCount, accTmp.Balance)
assert.Equal(t, p1.TotalCount, accTmp.Frozen)
receiptDate := &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err := exec.ExecLocal(createTx, receiptDate, int(1))
assert.Nil(t, err)
assert.NotNil(t, set)
// 提币
p2 := &pty.UnfreezeWithdraw{
UnfreezeID: string(unfreezeID(createTx.Hash())),
}
withdrawTx, err := ty.RPC_UnfreezeWithdrawTx(p2)
if err != nil {
t.Error("RPC_UnfreezeWithdrawTx", "err", err)
}
withdrawTx, err = signTx(withdrawTx, PrivKeyB)
if err != nil {
t.Error("RPC_UnfreezeWithdrawTx sign", "err", err)
}
blockTime := int64(10)
exec.SetEnv(env.blockHeight+1, env.blockTime+blockTime, env.difficulty)
receipt, err = exec.Exec(withdrawTx, 1)
assert.Nil(t, err)
assert.NotNil(t, receipt)
//t.Log(receipt)
accATmp := accA.LoadExecAccount(accountA.Addr, execAddr)
accBTmp := accB.LoadExecAccount(accountB.Addr, execAddr)
assert.Equal(t, total-p1.TotalCount, accATmp.Balance)
u := pty.Unfreeze{}
e := types.Decode(receipt.KV[2].Value, &u)
assert.Nil(t, e)
assert.Equal(t, u.Remaining, accATmp.Frozen)
assert.Equal(t, accountB.Balance+p1.TotalCount-u.Remaining, accBTmp.Balance)
receiptDate2 := &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err = exec.ExecLocal(withdrawTx, receiptDate2, int(1))
assert.Nil(t, err)
assert.NotNil(t, set)
// 不是受益人提币
{
p2 := &pty.UnfreezeWithdraw{
UnfreezeID: string(unfreezeID(createTx.Hash())),
}
withdrawTx, err := ty.RPC_UnfreezeWithdrawTx(p2)
if err != nil {
t.Error("RPC_UnfreezeWithdrawTx", "err", err)
}
withdrawTx, err = signTx(withdrawTx, PrivKeyC)
if err != nil {
t.Error("RPC_UnfreezeWithdrawTx sign", "err", err)
}
blockTime := int64(10)
exec.SetEnv(env.blockHeight+1, env.blockTime+blockTime, env.difficulty)
receipt, err = exec.Exec(withdrawTx, 1)
assert.Equal(t, pty.ErrNoPrivilege, err)
assert.Nil(t, receipt)
}
// 不是创建者终止
{
p3 := &pty.UnfreezeTerminate{
UnfreezeID: string(unfreezeID(createTx.Hash())),
}
terminateTx, err := ty.RPC_UnfreezeTerminateTx(p3)
if err != nil {
t.Error("RPC_UnfreezeTerminateTx", "err", err)
}
terminateTx, err = signTx(terminateTx, PrivKeyC)
if err != nil {
t.Error("RPC_UnfreezeTerminateTx sign", "err", err)
}
receipt, err = exec.Exec(terminateTx, 1)
assert.Equal(t, pty.ErrNoPrivilege, err)
assert.Nil(t, receipt)
}
// 终止
p3 := &pty.UnfreezeTerminate{
UnfreezeID: string(unfreezeID(createTx.Hash())),
}
terminateTx, err := ty.RPC_UnfreezeTerminateTx(p3)
if err != nil {
t.Error("RPC_UnfreezeTerminateTx", "err", err)
}
terminateTx, err = signTx(terminateTx, PrivKeyA)
if err != nil {
t.Error("RPC_UnfreezeTerminateTx sign", "err", err)
}
receipt, err = exec.Exec(terminateTx, 1)
assert.Nil(t, err)
assert.NotNil(t, receipt)
//t.Log(receipt)
accATmp = accA.LoadExecAccount(accountA.Addr, execAddr)
assert.Equal(t, total+total, accATmp.Balance+accBTmp.Balance)
assert.Equal(t, int64(0), accATmp.Frozen)
receiptDate3 := &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err = exec.ExecLocal(terminateTx, receiptDate3, int(1))
assert.Nil(t, err)
assert.NotNil(t, set)
// 终止后不能继续提币
{
p2 := &pty.UnfreezeWithdraw{
UnfreezeID: string(unfreezeID(createTx.Hash())),
}
withdrawTx, err := ty.RPC_UnfreezeWithdrawTx(p2)
if err != nil {
t.Error("RPC_UnfreezeWithdrawTx", "err", err)
}
withdrawTx, err = signTx(withdrawTx, PrivKeyB)
if err != nil {
t.Error("RPC_UnfreezeWithdrawTx sign", "err", err)
}
blockTime := int64(10)
exec.SetEnv(env.blockHeight+1, env.blockTime+blockTime+blockTime, env.difficulty)
receipt, err = exec.Exec(withdrawTx, 1)
assert.Equal(t, pty.ErrUnfreezeEmptied, err)
assert.Nil(t, receipt)
}
req := types.ReqString{Data: string(unfreezeID(createTx.Hash()))}
_, err = exec.Query("GetUnfreeze", types.Encode(&req))
assert.Nil(t, err)
_, err = exec.Query("GetUnfreezeWithdraw", types.Encode(&req))
assert.Nil(t, err)
_, err = exec.ExecDelLocal(terminateTx, receiptDate3, int(1))
assert.Nil(t, err)
_, err = exec.ExecDelLocal(withdrawTx, receiptDate2, int(1))
assert.Nil(t, err)
_, err = exec.ExecDelLocal(createTx, receiptDate, int(1))
assert.Nil(t, err)
}
func signTx(tx *types.Transaction, hexPrivKey string) (*types.Transaction, error) {
signType := types.SECP256K1
c, err := crypto.New(types.GetSignName(pty.UnfreezeX, signType))
if err != nil {
return tx, err
}
bytes, err := common.FromHex(hexPrivKey[:])
if err != nil {
return tx, err
}
privKey, err := c.PrivKeyFromBytes(bytes)
if err != nil {
return tx, err
}
tx.Sign(int32(signType), privKey)
return tx, 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 executor
import (
"fmt"
"github.com/33cn/chain33/common"
pty "github.com/33cn/plugin/plugin/dapp/unfreeze/types"
)
var (
id = "mavl-" + pty.UnfreezeX + "-"
initLocal = "LODB-" + pty.UnfreezeX + "-init-"
beneficiaryLocal = "LODB-" + pty.UnfreezeX + "-beneficiary-"
)
func unfreezeID(txHash []byte) []byte {
return []byte(fmt.Sprintf("%s%s", id, common.Bytes2Hex(txHash)))
}
func initKey(init string) []byte {
return []byte(fmt.Sprintf("%s%s", initLocal, init))
}
func beneficiaryKey(beneficiary string) []byte {
return []byte(fmt.Sprintf("%s%s", beneficiaryLocal, beneficiary))
}
// 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"
pty "github.com/33cn/plugin/plugin/dapp/unfreeze/types"
)
// Means 解冻算法接口
type Means interface {
setOpt(unfreeze *pty.Unfreeze, from *pty.UnfreezeCreate) (*pty.Unfreeze, error)
calcFrozen(unfreeze *pty.Unfreeze, now int64) (int64, error)
}
func newMeans(means string) (Means, error) {
if means == "FixAmount" {
return &fixAmount{}, nil
} else if means == "LeftProportion" {
return &leftProportion{}, nil
}
return nil, types.ErrNotSupport
}
type fixAmount struct {
}
func (opt *fixAmount) setOpt(unfreeze *pty.Unfreeze, from *pty.UnfreezeCreate) (*pty.Unfreeze, error) {
o := from.GetFixAmount()
if o == nil {
return nil, types.ErrInvalidParam
}
if o.Amount <= 0 || o.Period <= 0 {
return nil, types.ErrInvalidParam
}
unfreeze.MeansOpt = &pty.Unfreeze_FixAmount{FixAmount: from.GetFixAmount()}
return unfreeze, nil
}
func (opt *fixAmount) calcFrozen(unfreeze *pty.Unfreeze, now int64) (int64, error) {
means := unfreeze.GetFixAmount()
if means == nil {
return 0, types.ErrInvalidParam
}
unfreezeTimes := (now + means.Period - unfreeze.StartTime) / means.Period
unfreezeAmount := means.Amount * unfreezeTimes
if unfreeze.TotalCount <= unfreezeAmount {
return 0, nil
}
return unfreeze.TotalCount - unfreezeAmount, nil
}
type leftProportion struct {
}
func (opt *leftProportion) setOpt(unfreeze *pty.Unfreeze, from *pty.UnfreezeCreate) (*pty.Unfreeze, error) {
o := from.GetLeftProportion()
if o == nil {
return nil, types.ErrInvalidParam
}
if o.Period <= 0 || o.TenThousandth <= 0 {
return nil, types.ErrInvalidParam
}
unfreeze.MeansOpt = &pty.Unfreeze_LeftProportion{LeftProportion: from.GetLeftProportion()}
return unfreeze, nil
}
func (opt *leftProportion) calcFrozen(unfreeze *pty.Unfreeze, now int64) (int64, error) {
means := unfreeze.GetLeftProportion()
if means == nil {
return 0, types.ErrInvalidParam
}
unfreezeTimes := (now + means.Period - unfreeze.StartTime) / means.Period
frozen := float64(unfreeze.TotalCount)
for i := int64(0); i < unfreezeTimes; i++ {
frozen = frozen * float64(10000-means.TenThousandth) / 10000
}
return int64(frozen), nil
}
func withdraw(unfreeze *pty.Unfreeze, frozen int64) (*pty.Unfreeze, int64) {
if unfreeze.Remaining == 0 {
return unfreeze, 0
}
amount := unfreeze.Remaining - frozen
unfreeze.Remaining = frozen
return unfreeze, amount
}
package executor
import (
"testing"
"github.com/stretchr/testify/assert"
pty "github.com/33cn/plugin/plugin/dapp/unfreeze/types"
)
func TestCalcFrozen(t *testing.T) {
m, err := newMeans("LeftProportion")
assert.Nil(t, err)
assert.NotNil(t, m)
cases := []struct {
start int64
now int64
period int64
total int64
tenThousandth int64
expect int64
}{
{10000, 10001, 10, 10000, 2, 9998},
{10000, 10011, 10, 10000, 2, 9996},
{10000, 10001, 10, 1e17, 2, 9998 * 1e13},
{10000, 10011, 10, 1e17, 2, 9998 * 9998 * 1e9},
}
for _, c := range cases {
c := c
t.Run("test LeftProportion", func(t *testing.T) {
create := pty.UnfreezeCreate{
StartTime: c.start,
AssetExec: "coins",
AssetSymbol: "bty",
TotalCount: c.total,
Beneficiary: "x",
Means: "LeftProportion",
MeansOpt: &pty.UnfreezeCreate_LeftProportion{
LeftProportion: &pty.LeftProportion{
Period: c.period,
TenThousandth: c.tenThousandth,
},
},
}
u := &pty.Unfreeze{
TotalCount: c.total,
Means: "LeftProportion",
StartTime: c.start,
MeansOpt: &pty.Unfreeze_LeftProportion{
LeftProportion: &pty.LeftProportion{
Period: c.period,
TenThousandth: c.tenThousandth,
},
},
}
u, err = m.setOpt(u, &create)
assert.Nil(t, err)
f, err := m.calcFrozen(u, c.now)
assert.Nil(t, err)
assert.Equal(t, c.expect, f)
})
}
}
// 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 (
"time"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
pty "github.com/33cn/plugin/plugin/dapp/unfreeze/types"
)
// Query_GetUnfreezeWithdraw 查询合约可提币量
func (u *Unfreeze) Query_GetUnfreezeWithdraw(in *types.ReqString) (types.Message, error) {
return QueryWithdraw(u.GetStateDB(), in.GetData())
}
// Query_GetUnfreeze 查询合约状态
func (u *Unfreeze) Query_GetUnfreeze(in *types.ReqString) (types.Message, error) {
return QueryUnfreeze(u.GetStateDB(), in.GetData())
}
// QueryWithdraw 查询可提币状态
func QueryWithdraw(stateDB dbm.KV, unfreezeID string) (types.Message, error) {
unfreeze, err := loadUnfreeze(unfreezeID, stateDB)
if err != nil {
uflog.Error("QueryWithdraw ", "unfreezeID", unfreezeID, "err", err)
return nil, err
}
currentTime := time.Now().Unix()
reply := &pty.ReplyQueryUnfreezeWithdraw{UnfreezeID: unfreezeID}
available, err := getWithdrawAvailable(unfreeze, currentTime)
if err != nil {
return nil, err
}
reply.AvailableAmount = available
return reply, nil
}
func getWithdrawAvailable(unfreeze *pty.Unfreeze, calcTime int64) (int64, error) {
means, err := newMeans(unfreeze.Means)
if err != nil {
return 0, err
}
frozen, err := means.calcFrozen(unfreeze, calcTime)
if err != nil {
return 0, err
}
_, amount := withdraw(unfreeze, frozen)
return amount, nil
}
// QueryUnfreeze 查询合约状态
func QueryUnfreeze(stateDB dbm.KV, unfreezeID string) (types.Message, error) {
unfreeze, err := loadUnfreeze(unfreezeID, stateDB)
if err != nil {
uflog.Error("QueryUnfreeze ", "unfreezeID", unfreezeID, "err", err)
return nil, err
}
return unfreeze, 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 executor
import (
log "github.com/33cn/chain33/common/log/log15"
drivers "github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
uf "github.com/33cn/plugin/plugin/dapp/unfreeze/types"
)
var uflog = log.New("module", "execs.unfreeze")
var driverName = uf.UnfreezeX
func init() {
ety := types.LoadExecutorType(driverName)
ety.InitFuncList(types.ListMethod(&Unfreeze{}))
}
// Init 重命名执行器名称
func Init(name string, sub []byte) {
drivers.Register(GetName(), newUnfreeze, 0)
}
// Unfreeze 执行器结构体
type Unfreeze struct {
drivers.DriverBase
}
func newUnfreeze() drivers.Driver {
t := &Unfreeze{}
t.SetChild(t)
t.SetExecutorType(types.LoadExecutorType(driverName))
return t
}
// GetName 获得执行器名字
func GetName() string {
return newUnfreeze().GetName()
}
// GetDriverName 获得驱动名字
func (u *Unfreeze) GetDriverName() string {
return driverName
}
// 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 unfreeze
import (
"github.com/33cn/chain33/pluginmgr"
"github.com/33cn/plugin/plugin/dapp/unfreeze/commands"
"github.com/33cn/plugin/plugin/dapp/unfreeze/executor"
"github.com/33cn/plugin/plugin/dapp/unfreeze/rpc"
uf "github.com/33cn/plugin/plugin/dapp/unfreeze/types"
)
func init() {
pluginmgr.Register(&pluginmgr.PluginBase{
Name: uf.PackageName,
ExecName: executor.GetName(),
Exec: executor.Init,
Cmd: commands.Cmd,
RPC: rpc.Init,
})
}
// 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.
all:
./create_protobuf.sh
#!/bin/sh
protoc --go_out=plugins=grpc:../types ./*.proto --proto_path=. --proto_path="$GOPATH/src/github.com/33cn/chain33/types/proto/"
// 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.
syntax = "proto3";
import "common.proto";
package types;
message Unfreeze {
//解冻交易ID(唯一识别码)
string unfreezeID = 1;
//开始时间
int64 startTime = 2;
//币种
string assetExec = 3;
string assetSymbol = 4;
//冻结总额
int64 totalCount = 5;
//发币人地址
string initiator = 6;
//收币人地址
string beneficiary = 7;
//解冻剩余币数
int64 remaining = 8;
//解冻方式(百分比;固额)
string means = 9;
oneof meansOpt {
FixAmount fixAmount = 10;
LeftProportion leftProportion = 11;
}
}
// 按时间固定额度解冻
message FixAmount {
int64 period = 1;
int64 amount = 2;
}
// 固定时间间隔按余量百分比解冻
message LeftProportion {
int64 period = 1;
int64 tenThousandth = 2;
}
// message for execs.unfreeze
message UnfreezeAction {
oneof value {
UnfreezeCreate create = 1;
UnfreezeWithdraw withdraw = 2;
UnfreezeTerminate terminate = 3;
}
int32 ty = 4;
}
// action
message UnfreezeCreate {
int64 startTime = 1;
string assetExec = 2;
string assetSymbol = 3;
int64 totalCount = 4;
string beneficiary = 5;
string means = 6;
oneof meansOpt {
FixAmount fixAmount = 7;
LeftProportion leftProportion = 8;
}
}
message UnfreezeWithdraw {
string unfreezeID = 1;
}
message UnfreezeTerminate {
string unfreezeID = 1;
}
// receipt
message ReceiptUnfreeze {
Unfreeze prev = 1;
Unfreeze current = 2;
}
// query
message ReplyQueryUnfreezeWithdraw {
string unfreezeID = 1;
int64 availableAmount = 2;
}
// TODO 类型应该大写还是小写
service unfreeze {
rpc GetUnfreezeWithdraw(ReqString) returns (ReplyQueryUnfreezeWithdraw) {}
rpc QueryUnfreeze(ReqString) returns (Unfreeze) {}
}
\ 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
import (
"context"
"encoding/hex"
"github.com/33cn/chain33/types"
pty "github.com/33cn/plugin/plugin/dapp/unfreeze/types"
)
// GetUnfreeze 获得冻结合约
func (c *channelClient) GetUnfreeze(ctx context.Context, in *types.ReqString) (*pty.Unfreeze, error) {
v, err := c.Query(pty.UnfreezeX, "GetUnfreeze", in)
if err != nil {
return nil, err
}
if resp, ok := v.(*pty.Unfreeze); ok {
return resp, nil
}
return nil, types.ErrDecode
}
// GetUnfreezeWithdraw 获得冻结合约可提币量
func (c *channelClient) GetUnfreezeWithdraw(ctx context.Context, in *types.ReqString) (*pty.ReplyQueryUnfreezeWithdraw, error) {
v, err := c.Query(pty.UnfreezeX, "GetUnfreezeWithdraw", in)
if err != nil {
return nil, err
}
if resp, ok := v.(*pty.ReplyQueryUnfreezeWithdraw); ok {
return resp, nil
}
return nil, types.ErrDecode
}
// GetUnfreeze 获得冻结合约
func (c *Jrpc) GetUnfreeze(in *types.ReqString, result *interface{}) error {
v, err := c.cli.GetUnfreeze(context.Background(), in)
if err != nil {
return err
}
*result = v
return nil
}
// GetUnfreezeWithdraw 获得冻结合约可提币量
func (c *Jrpc) GetUnfreezeWithdraw(in *types.ReqString, result *interface{}) error {
v, err := c.cli.GetUnfreezeWithdraw(context.Background(), in)
if err != nil {
return err
}
*result = v
return nil
}
// CreateRawUnfreezeCreate 创建冻结合约
func (c *Jrpc) CreateRawUnfreezeCreate(param *pty.UnfreezeCreate, result *interface{}) error {
if param == nil {
return types.ErrInvalidParam
}
data, err := types.CallCreateTx(types.ExecName(pty.UnfreezeX), "UnfreezeCreateTX", param)
if err != nil {
return err
}
*result = hex.EncodeToString(data)
return nil
}
// CreateRawUnfreezeWithdraw 创建提币交易
func (c *Jrpc) CreateRawUnfreezeWithdraw(param *pty.UnfreezeWithdraw, result *interface{}) error {
if param == nil {
return types.ErrInvalidParam
}
data, err := types.CallCreateTx(types.ExecName(pty.UnfreezeX), "UnfreezeWithdrawTx", param)
if err != nil {
return err
}
*result = hex.EncodeToString(data)
return nil
}
// CreateRawUnfreezeTerminate 终止冻结合约
func (c *Jrpc) CreateRawUnfreezeTerminate(param *pty.UnfreezeTerminate, result *interface{}) error {
if param == nil {
return types.ErrInvalidParam
}
data, err := types.CallCreateTx(types.ExecName(pty.UnfreezeX), "UnfreezeTerminateTx", param)
if err != nil {
return err
}
*result = hex.EncodeToString(data)
return 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 rpc
import (
"github.com/33cn/chain33/rpc/types"
)
// Jrpc json rpc struct
type Jrpc struct {
cli *channelClient
}
// Grpc grpc struct
type Grpc struct {
*channelClient
}
type channelClient struct {
types.ChannelClient
}
// Init init grpc param
func Init(name string, s types.RPCServer) {
cli := &channelClient{}
grpc := &Grpc{channelClient: cli}
cli.Init(name, s, &Jrpc{cli: cli}, grpc)
}
// 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
//unfreeze action ty
const (
UnfreezeActionCreate = iota + 1
UnfreezeActionWithdraw
UnfreezeActionTerminate
//log for unfreeze
TyLogCreateUnfreeze = 2001 // TODO 修改具体编号
TyLogWithdrawUnfreeze = 2002
TyLogTerminateUnfreeze = 2003
)
const (
// Action_CreateUnfreeze Action 名字
Action_CreateUnfreeze = "createUnfreeze"
// Action_WithdrawUnfreeze Action 名字
Action_WithdrawUnfreeze = "withdrawUnfreeze"
// Action_TerminateUnfreeze Action 名字
Action_TerminateUnfreeze = "terminateUnfreeze"
)
const (
// FuncName_QueryUnfreezeWithdraw 查询方法名
FuncName_QueryUnfreezeWithdraw = "QueryUnfreezeWithdraw"
)
//包的名字可以通过配置文件来配置
//建议用github的组织名称,或者用户名字开头, 再加上自己的插件的名字
//如果发生重名,可以通过配置文件修改这些名字
var (
PackageName = "chain33.unfreeze"
RPCName = "Chain33.Unfreeze"
UnfreezeX = "unfreeze"
ExecerUnfreeze = []byte(UnfreezeX)
FixAmountX = "FixAmount"
LeftProportionX = "LeftProportion"
SupportMeans = []string{"FixAmount", "LeftProportion"}
)
// 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 (
// ErrUnfreezeEmptied 没有可提币量
ErrUnfreezeEmptied = errors.New("ErrUnfreezeEmptied")
// ErrUnfreezeMeans 解冻币算法错误
ErrUnfreezeMeans = errors.New("ErrUnfreezeMeans")
// ErrUnfreezeID 冻结合约ID错误
ErrUnfreezeID = errors.New("ErrUnfreezeID")
// ErrNoPrivilege 没有权限
ErrNoPrivilege = errors.New("ErrNoPrivilege")
)
// 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
// 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 (
"encoding/json"
"math/rand"
"reflect"
"time"
"github.com/33cn/chain33/common/address"
log "github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/types"
)
var name string
var tlog = log.New("module", name)
func init() {
name = UnfreezeX
types.AllowUserExec = append(types.AllowUserExec, []byte(UnfreezeX))
// init executor type
types.RegistorExecutor(name, NewType())
}
//getRealExecName
func getRealExecName(paraName string) string {
return types.ExecName(paraName + UnfreezeX)
}
// NewType 生成新的基础类型
func NewType() *UnfreezeType {
c := &UnfreezeType{}
c.SetChild(c)
return c
}
// UnfreezeType 基础类型结构体
type UnfreezeType struct {
types.ExecTypeBase
}
// GetLogMap 获得日志类型列表
func (u *UnfreezeType) GetLogMap() map[int64]*types.LogInfo {
return map[int64]*types.LogInfo{
TyLogCreateUnfreeze: {Ty: reflect.TypeOf(ReceiptUnfreeze{}), Name: "LogCreateUnfreeze"},
TyLogWithdrawUnfreeze: {Ty: reflect.TypeOf(ReceiptUnfreeze{}), Name: "LogWithdrawUnfreeze"},
TyLogTerminateUnfreeze: {Ty: reflect.TypeOf(ReceiptUnfreeze{}), Name: "LogTerminateUnfreeze"},
}
}
// GetPayload 获得空的Unfreeze 的 Payload
func (u *UnfreezeType) GetPayload() types.Message {
return &UnfreezeAction{}
}
// GetTypeMap 获得Action 方法列表
func (u *UnfreezeType) GetTypeMap() map[string]int32 {
return map[string]int32{
"Create": UnfreezeActionCreate,
"Withdraw": UnfreezeActionWithdraw,
"Terminate": UnfreezeActionTerminate,
}
}
// CreateTx 创建交易
func (u UnfreezeType) CreateTx(action string, message json.RawMessage) (*types.Transaction, error) {
tlog.Debug("UnfreezeType.CreateTx", "action", action)
if action == Action_CreateUnfreeze {
var param UnfreezeCreate
err := json.Unmarshal(message, &param)
if err != nil {
tlog.Error("CreateTx", "Error", err)
return nil, types.ErrInvalidParam
}
return u.RPC_UnfreezeCreateTx(&param)
} else if action == Action_WithdrawUnfreeze {
var param UnfreezeWithdraw
err := json.Unmarshal(message, &param)
if err != nil {
tlog.Error("CreateTx", "Error", err)
return nil, types.ErrInvalidParam
}
return u.RPC_UnfreezeWithdrawTx(&param)
} else if action == Action_TerminateUnfreeze {
var param UnfreezeTerminate
err := json.Unmarshal(message, &param)
if err != nil {
tlog.Error("CreateTx", "Error", err)
return nil, types.ErrInvalidParam
}
return u.RPC_UnfreezeTerminateTx(&param)
}
return nil, types.ErrNotSupport
}
// RPC_UnfreezeCreateTx 创建冻结合约交易入口
func (u UnfreezeType) RPC_UnfreezeCreateTx(parm *UnfreezeCreate) (*types.Transaction, error) {
return CreateUnfreezeCreateTx(types.GetParaName(), parm)
}
// CreateUnfreezeCreateTx 创建冻结合约交易
func CreateUnfreezeCreateTx(title string, parm *UnfreezeCreate) (*types.Transaction, error) {
if parm == nil {
tlog.Error("RPC_UnfreezeCreateTx", "parm", parm)
return nil, types.ErrInvalidParam
}
if parm.AssetExec == "" || parm.AssetSymbol == "" || parm.TotalCount <= 0 || parm.Means == "" {
tlog.Error("RPC_UnfreezeCreateTx", "parm", parm)
return nil, types.ErrInvalidParam
}
if !supportMeans(parm.Means) {
tlog.Error("RPC_UnfreezeCreateTx not support means", "parm", parm)
return nil, types.ErrInvalidParam
}
create := &UnfreezeAction{
Ty: UnfreezeActionCreate,
Value: &UnfreezeAction_Create{parm},
}
tx := &types.Transaction{
Execer: []byte(getRealExecName(title)),
Payload: types.Encode(create),
Nonce: rand.New(rand.NewSource(time.Now().UnixNano())).Int63(),
To: address.ExecAddress(getRealExecName(types.GetParaName())),
}
tx.SetRealFee(types.GInt("MinFee"))
return tx, nil
}
// RPC_UnfreezeWithdrawTx 创建提币交易入口
func (u UnfreezeType) RPC_UnfreezeWithdrawTx(parm *UnfreezeWithdraw) (*types.Transaction, error) {
return CreateUnfreezeWithdrawTx(types.GetParaName(), parm)
}
// CreateUnfreezeWithdrawTx 创建提币交易
func CreateUnfreezeWithdrawTx(title string, parm *UnfreezeWithdraw) (*types.Transaction, error) {
if parm == nil {
tlog.Error("RPC_UnfreezeWithdrawTx", "parm", parm)
return nil, types.ErrInvalidParam
}
v := &UnfreezeWithdraw{
UnfreezeID: parm.UnfreezeID,
}
withdraw := &UnfreezeAction{
Ty: UnfreezeActionWithdraw,
Value: &UnfreezeAction_Withdraw{v},
}
tx := &types.Transaction{
Execer: []byte(getRealExecName(title)),
Payload: types.Encode(withdraw),
Nonce: rand.New(rand.NewSource(time.Now().UnixNano())).Int63(),
To: address.ExecAddress(getRealExecName(types.GetParaName())),
}
tx.SetRealFee(types.GInt("MinFee"))
return tx, nil
}
// RPC_UnfreezeTerminateTx 创建终止冻结合约入口
func (u UnfreezeType) RPC_UnfreezeTerminateTx(parm *UnfreezeTerminate) (*types.Transaction, error) {
return CreateUnfreezeTerminateTx(types.GetParaName(), parm)
}
// CreateUnfreezeTerminateTx 创建终止冻结合约
func CreateUnfreezeTerminateTx(title string, parm *UnfreezeTerminate) (*types.Transaction, error) {
if parm == nil {
tlog.Error("RPC_UnfreezeTerminateTx", "parm", parm)
return nil, types.ErrInvalidParam
}
v := &UnfreezeTerminate{
UnfreezeID: parm.UnfreezeID,
}
terminate := &UnfreezeAction{
Ty: UnfreezeActionTerminate,
Value: &UnfreezeAction_Terminate{v},
}
tx := &types.Transaction{
Execer: []byte(getRealExecName(title)),
Payload: types.Encode(terminate),
Nonce: rand.New(rand.NewSource(time.Now().UnixNano())).Int63(),
To: address.ExecAddress(getRealExecName(types.GetParaName())),
}
tx.SetRealFee(types.GInt("MinFee"))
return tx, nil
}
func supportMeans(means string) bool {
for _, m := range SupportMeans {
if m == means {
return true
}
}
return false
}
// 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.
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: unfreeze.proto
/*
Package types is a generated protocol buffer package.
It is generated from these files:
unfreeze.proto
It has these top-level messages:
Unfreeze
FixAmount
LeftProportion
UnfreezeAction
UnfreezeCreate
UnfreezeWithdraw
UnfreezeTerminate
ReceiptUnfreeze
ReplyQueryUnfreezeWithdraw
*/
package types
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import types1 "github.com/33cn/chain33/types"
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type Unfreeze struct {
// 解冻交易ID(唯一识别码)
UnfreezeID string `protobuf:"bytes,1,opt,name=unfreezeID" json:"unfreezeID,omitempty"`
// 开始时间
StartTime int64 `protobuf:"varint,2,opt,name=startTime" json:"startTime,omitempty"`
// 币种
AssetExec string `protobuf:"bytes,3,opt,name=assetExec" json:"assetExec,omitempty"`
AssetSymbol string `protobuf:"bytes,4,opt,name=assetSymbol" json:"assetSymbol,omitempty"`
// 冻结总额
TotalCount int64 `protobuf:"varint,5,opt,name=totalCount" json:"totalCount,omitempty"`
// 发币人地址
Initiator string `protobuf:"bytes,6,opt,name=initiator" json:"initiator,omitempty"`
// 收币人地址
Beneficiary string `protobuf:"bytes,7,opt,name=beneficiary" json:"beneficiary,omitempty"`
// 解冻剩余币数
Remaining int64 `protobuf:"varint,8,opt,name=remaining" json:"remaining,omitempty"`
// 解冻方式(百分比;固额)
Means string `protobuf:"bytes,9,opt,name=means" json:"means,omitempty"`
// Types that are valid to be assigned to MeansOpt:
// *Unfreeze_FixAmount
// *Unfreeze_LeftProportion
MeansOpt isUnfreeze_MeansOpt `protobuf_oneof:"meansOpt"`
}
func (m *Unfreeze) Reset() { *m = Unfreeze{} }
func (m *Unfreeze) String() string { return proto.CompactTextString(m) }
func (*Unfreeze) ProtoMessage() {}
func (*Unfreeze) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
type isUnfreeze_MeansOpt interface {
isUnfreeze_MeansOpt()
}
type Unfreeze_FixAmount struct {
FixAmount *FixAmount `protobuf:"bytes,10,opt,name=fixAmount,oneof"`
}
type Unfreeze_LeftProportion struct {
LeftProportion *LeftProportion `protobuf:"bytes,11,opt,name=leftProportion,oneof"`
}
func (*Unfreeze_FixAmount) isUnfreeze_MeansOpt() {}
func (*Unfreeze_LeftProportion) isUnfreeze_MeansOpt() {}
func (m *Unfreeze) GetMeansOpt() isUnfreeze_MeansOpt {
if m != nil {
return m.MeansOpt
}
return nil
}
func (m *Unfreeze) GetUnfreezeID() string {
if m != nil {
return m.UnfreezeID
}
return ""
}
func (m *Unfreeze) GetStartTime() int64 {
if m != nil {
return m.StartTime
}
return 0
}
func (m *Unfreeze) GetAssetExec() string {
if m != nil {
return m.AssetExec
}
return ""
}
func (m *Unfreeze) GetAssetSymbol() string {
if m != nil {
return m.AssetSymbol
}
return ""
}
func (m *Unfreeze) GetTotalCount() int64 {
if m != nil {
return m.TotalCount
}
return 0
}
func (m *Unfreeze) GetInitiator() string {
if m != nil {
return m.Initiator
}
return ""
}
func (m *Unfreeze) GetBeneficiary() string {
if m != nil {
return m.Beneficiary
}
return ""
}
func (m *Unfreeze) GetRemaining() int64 {
if m != nil {
return m.Remaining
}
return 0
}
func (m *Unfreeze) GetMeans() string {
if m != nil {
return m.Means
}
return ""
}
func (m *Unfreeze) GetFixAmount() *FixAmount {
if x, ok := m.GetMeansOpt().(*Unfreeze_FixAmount); ok {
return x.FixAmount
}
return nil
}
func (m *Unfreeze) GetLeftProportion() *LeftProportion {
if x, ok := m.GetMeansOpt().(*Unfreeze_LeftProportion); ok {
return x.LeftProportion
}
return nil
}
// XXX_OneofFuncs is for the internal use of the proto package.
func (*Unfreeze) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
return _Unfreeze_OneofMarshaler, _Unfreeze_OneofUnmarshaler, _Unfreeze_OneofSizer, []interface{}{
(*Unfreeze_FixAmount)(nil),
(*Unfreeze_LeftProportion)(nil),
}
}
func _Unfreeze_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*Unfreeze)
// meansOpt
switch x := m.MeansOpt.(type) {
case *Unfreeze_FixAmount:
b.EncodeVarint(10<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.FixAmount); err != nil {
return err
}
case *Unfreeze_LeftProportion:
b.EncodeVarint(11<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.LeftProportion); err != nil {
return err
}
case nil:
default:
return fmt.Errorf("Unfreeze.MeansOpt has unexpected type %T", x)
}
return nil
}
func _Unfreeze_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
m := msg.(*Unfreeze)
switch tag {
case 10: // meansOpt.fixAmount
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(FixAmount)
err := b.DecodeMessage(msg)
m.MeansOpt = &Unfreeze_FixAmount{msg}
return true, err
case 11: // meansOpt.leftProportion
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(LeftProportion)
err := b.DecodeMessage(msg)
m.MeansOpt = &Unfreeze_LeftProportion{msg}
return true, err
default:
return false, nil
}
}
func _Unfreeze_OneofSizer(msg proto.Message) (n int) {
m := msg.(*Unfreeze)
// meansOpt
switch x := m.MeansOpt.(type) {
case *Unfreeze_FixAmount:
s := proto.Size(x.FixAmount)
n += proto.SizeVarint(10<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case *Unfreeze_LeftProportion:
s := proto.Size(x.LeftProportion)
n += proto.SizeVarint(11<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case nil:
default:
panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
}
return n
}
// 按时间固定额度解冻
type FixAmount struct {
Period int64 `protobuf:"varint,1,opt,name=period" json:"period,omitempty"`
Amount int64 `protobuf:"varint,2,opt,name=amount" json:"amount,omitempty"`
}
func (m *FixAmount) Reset() { *m = FixAmount{} }
func (m *FixAmount) String() string { return proto.CompactTextString(m) }
func (*FixAmount) ProtoMessage() {}
func (*FixAmount) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *FixAmount) GetPeriod() int64 {
if m != nil {
return m.Period
}
return 0
}
func (m *FixAmount) GetAmount() int64 {
if m != nil {
return m.Amount
}
return 0
}
// 固定时间间隔按余量百分比解冻
type LeftProportion struct {
Period int64 `protobuf:"varint,1,opt,name=period" json:"period,omitempty"`
TenThousandth int64 `protobuf:"varint,2,opt,name=tenThousandth" json:"tenThousandth,omitempty"`
}
func (m *LeftProportion) Reset() { *m = LeftProportion{} }
func (m *LeftProportion) String() string { return proto.CompactTextString(m) }
func (*LeftProportion) ProtoMessage() {}
func (*LeftProportion) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
func (m *LeftProportion) GetPeriod() int64 {
if m != nil {
return m.Period
}
return 0
}
func (m *LeftProportion) GetTenThousandth() int64 {
if m != nil {
return m.TenThousandth
}
return 0
}
// message for execs.unfreeze
type UnfreezeAction struct {
// Types that are valid to be assigned to Value:
// *UnfreezeAction_Create
// *UnfreezeAction_Withdraw
// *UnfreezeAction_Terminate
Value isUnfreezeAction_Value `protobuf_oneof:"value"`
Ty int32 `protobuf:"varint,4,opt,name=ty" json:"ty,omitempty"`
}
func (m *UnfreezeAction) Reset() { *m = UnfreezeAction{} }
func (m *UnfreezeAction) String() string { return proto.CompactTextString(m) }
func (*UnfreezeAction) ProtoMessage() {}
func (*UnfreezeAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
type isUnfreezeAction_Value interface {
isUnfreezeAction_Value()
}
type UnfreezeAction_Create struct {
Create *UnfreezeCreate `protobuf:"bytes,1,opt,name=create,oneof"`
}
type UnfreezeAction_Withdraw struct {
Withdraw *UnfreezeWithdraw `protobuf:"bytes,2,opt,name=withdraw,oneof"`
}
type UnfreezeAction_Terminate struct {
Terminate *UnfreezeTerminate `protobuf:"bytes,3,opt,name=terminate,oneof"`
}
func (*UnfreezeAction_Create) isUnfreezeAction_Value() {}
func (*UnfreezeAction_Withdraw) isUnfreezeAction_Value() {}
func (*UnfreezeAction_Terminate) isUnfreezeAction_Value() {}
func (m *UnfreezeAction) GetValue() isUnfreezeAction_Value {
if m != nil {
return m.Value
}
return nil
}
func (m *UnfreezeAction) GetCreate() *UnfreezeCreate {
if x, ok := m.GetValue().(*UnfreezeAction_Create); ok {
return x.Create
}
return nil
}
func (m *UnfreezeAction) GetWithdraw() *UnfreezeWithdraw {
if x, ok := m.GetValue().(*UnfreezeAction_Withdraw); ok {
return x.Withdraw
}
return nil
}
func (m *UnfreezeAction) GetTerminate() *UnfreezeTerminate {
if x, ok := m.GetValue().(*UnfreezeAction_Terminate); ok {
return x.Terminate
}
return nil
}
func (m *UnfreezeAction) GetTy() int32 {
if m != nil {
return m.Ty
}
return 0
}
// XXX_OneofFuncs is for the internal use of the proto package.
func (*UnfreezeAction) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
return _UnfreezeAction_OneofMarshaler, _UnfreezeAction_OneofUnmarshaler, _UnfreezeAction_OneofSizer, []interface{}{
(*UnfreezeAction_Create)(nil),
(*UnfreezeAction_Withdraw)(nil),
(*UnfreezeAction_Terminate)(nil),
}
}
func _UnfreezeAction_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*UnfreezeAction)
// value
switch x := m.Value.(type) {
case *UnfreezeAction_Create:
b.EncodeVarint(1<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.Create); err != nil {
return err
}
case *UnfreezeAction_Withdraw:
b.EncodeVarint(2<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.Withdraw); err != nil {
return err
}
case *UnfreezeAction_Terminate:
b.EncodeVarint(3<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.Terminate); err != nil {
return err
}
case nil:
default:
return fmt.Errorf("UnfreezeAction.Value has unexpected type %T", x)
}
return nil
}
func _UnfreezeAction_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
m := msg.(*UnfreezeAction)
switch tag {
case 1: // value.create
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(UnfreezeCreate)
err := b.DecodeMessage(msg)
m.Value = &UnfreezeAction_Create{msg}
return true, err
case 2: // value.withdraw
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(UnfreezeWithdraw)
err := b.DecodeMessage(msg)
m.Value = &UnfreezeAction_Withdraw{msg}
return true, err
case 3: // value.terminate
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(UnfreezeTerminate)
err := b.DecodeMessage(msg)
m.Value = &UnfreezeAction_Terminate{msg}
return true, err
default:
return false, nil
}
}
func _UnfreezeAction_OneofSizer(msg proto.Message) (n int) {
m := msg.(*UnfreezeAction)
// value
switch x := m.Value.(type) {
case *UnfreezeAction_Create:
s := proto.Size(x.Create)
n += proto.SizeVarint(1<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case *UnfreezeAction_Withdraw:
s := proto.Size(x.Withdraw)
n += proto.SizeVarint(2<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case *UnfreezeAction_Terminate:
s := proto.Size(x.Terminate)
n += proto.SizeVarint(3<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case nil:
default:
panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
}
return n
}
// action
type UnfreezeCreate struct {
StartTime int64 `protobuf:"varint,1,opt,name=startTime" json:"startTime,omitempty"`
AssetExec string `protobuf:"bytes,2,opt,name=assetExec" json:"assetExec,omitempty"`
AssetSymbol string `protobuf:"bytes,3,opt,name=assetSymbol" json:"assetSymbol,omitempty"`
TotalCount int64 `protobuf:"varint,4,opt,name=totalCount" json:"totalCount,omitempty"`
Beneficiary string `protobuf:"bytes,5,opt,name=beneficiary" json:"beneficiary,omitempty"`
Means string `protobuf:"bytes,6,opt,name=means" json:"means,omitempty"`
// Types that are valid to be assigned to MeansOpt:
// *UnfreezeCreate_FixAmount
// *UnfreezeCreate_LeftProportion
MeansOpt isUnfreezeCreate_MeansOpt `protobuf_oneof:"meansOpt"`
}
func (m *UnfreezeCreate) Reset() { *m = UnfreezeCreate{} }
func (m *UnfreezeCreate) String() string { return proto.CompactTextString(m) }
func (*UnfreezeCreate) ProtoMessage() {}
func (*UnfreezeCreate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
type isUnfreezeCreate_MeansOpt interface {
isUnfreezeCreate_MeansOpt()
}
type UnfreezeCreate_FixAmount struct {
FixAmount *FixAmount `protobuf:"bytes,7,opt,name=fixAmount,oneof"`
}
type UnfreezeCreate_LeftProportion struct {
LeftProportion *LeftProportion `protobuf:"bytes,8,opt,name=leftProportion,oneof"`
}
func (*UnfreezeCreate_FixAmount) isUnfreezeCreate_MeansOpt() {}
func (*UnfreezeCreate_LeftProportion) isUnfreezeCreate_MeansOpt() {}
func (m *UnfreezeCreate) GetMeansOpt() isUnfreezeCreate_MeansOpt {
if m != nil {
return m.MeansOpt
}
return nil
}
func (m *UnfreezeCreate) GetStartTime() int64 {
if m != nil {
return m.StartTime
}
return 0
}
func (m *UnfreezeCreate) GetAssetExec() string {
if m != nil {
return m.AssetExec
}
return ""
}
func (m *UnfreezeCreate) GetAssetSymbol() string {
if m != nil {
return m.AssetSymbol
}
return ""
}
func (m *UnfreezeCreate) GetTotalCount() int64 {
if m != nil {
return m.TotalCount
}
return 0
}
func (m *UnfreezeCreate) GetBeneficiary() string {
if m != nil {
return m.Beneficiary
}
return ""
}
func (m *UnfreezeCreate) GetMeans() string {
if m != nil {
return m.Means
}
return ""
}
func (m *UnfreezeCreate) GetFixAmount() *FixAmount {
if x, ok := m.GetMeansOpt().(*UnfreezeCreate_FixAmount); ok {
return x.FixAmount
}
return nil
}
func (m *UnfreezeCreate) GetLeftProportion() *LeftProportion {
if x, ok := m.GetMeansOpt().(*UnfreezeCreate_LeftProportion); ok {
return x.LeftProportion
}
return nil
}
// XXX_OneofFuncs is for the internal use of the proto package.
func (*UnfreezeCreate) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
return _UnfreezeCreate_OneofMarshaler, _UnfreezeCreate_OneofUnmarshaler, _UnfreezeCreate_OneofSizer, []interface{}{
(*UnfreezeCreate_FixAmount)(nil),
(*UnfreezeCreate_LeftProportion)(nil),
}
}
func _UnfreezeCreate_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*UnfreezeCreate)
// meansOpt
switch x := m.MeansOpt.(type) {
case *UnfreezeCreate_FixAmount:
b.EncodeVarint(7<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.FixAmount); err != nil {
return err
}
case *UnfreezeCreate_LeftProportion:
b.EncodeVarint(8<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.LeftProportion); err != nil {
return err
}
case nil:
default:
return fmt.Errorf("UnfreezeCreate.MeansOpt has unexpected type %T", x)
}
return nil
}
func _UnfreezeCreate_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
m := msg.(*UnfreezeCreate)
switch tag {
case 7: // meansOpt.fixAmount
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(FixAmount)
err := b.DecodeMessage(msg)
m.MeansOpt = &UnfreezeCreate_FixAmount{msg}
return true, err
case 8: // meansOpt.leftProportion
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(LeftProportion)
err := b.DecodeMessage(msg)
m.MeansOpt = &UnfreezeCreate_LeftProportion{msg}
return true, err
default:
return false, nil
}
}
func _UnfreezeCreate_OneofSizer(msg proto.Message) (n int) {
m := msg.(*UnfreezeCreate)
// meansOpt
switch x := m.MeansOpt.(type) {
case *UnfreezeCreate_FixAmount:
s := proto.Size(x.FixAmount)
n += proto.SizeVarint(7<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case *UnfreezeCreate_LeftProportion:
s := proto.Size(x.LeftProportion)
n += proto.SizeVarint(8<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case nil:
default:
panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
}
return n
}
type UnfreezeWithdraw struct {
UnfreezeID string `protobuf:"bytes,1,opt,name=unfreezeID" json:"unfreezeID,omitempty"`
}
func (m *UnfreezeWithdraw) Reset() { *m = UnfreezeWithdraw{} }
func (m *UnfreezeWithdraw) String() string { return proto.CompactTextString(m) }
func (*UnfreezeWithdraw) ProtoMessage() {}
func (*UnfreezeWithdraw) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
func (m *UnfreezeWithdraw) GetUnfreezeID() string {
if m != nil {
return m.UnfreezeID
}
return ""
}
type UnfreezeTerminate struct {
UnfreezeID string `protobuf:"bytes,1,opt,name=unfreezeID" json:"unfreezeID,omitempty"`
}
func (m *UnfreezeTerminate) Reset() { *m = UnfreezeTerminate{} }
func (m *UnfreezeTerminate) String() string { return proto.CompactTextString(m) }
func (*UnfreezeTerminate) ProtoMessage() {}
func (*UnfreezeTerminate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
func (m *UnfreezeTerminate) GetUnfreezeID() string {
if m != nil {
return m.UnfreezeID
}
return ""
}
// receipt
type ReceiptUnfreeze struct {
Prev *Unfreeze `protobuf:"bytes,1,opt,name=prev" json:"prev,omitempty"`
Current *Unfreeze `protobuf:"bytes,2,opt,name=current" json:"current,omitempty"`
}
func (m *ReceiptUnfreeze) Reset() { *m = ReceiptUnfreeze{} }
func (m *ReceiptUnfreeze) String() string { return proto.CompactTextString(m) }
func (*ReceiptUnfreeze) ProtoMessage() {}
func (*ReceiptUnfreeze) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
func (m *ReceiptUnfreeze) GetPrev() *Unfreeze {
if m != nil {
return m.Prev
}
return nil
}
func (m *ReceiptUnfreeze) GetCurrent() *Unfreeze {
if m != nil {
return m.Current
}
return nil
}
// query
type ReplyQueryUnfreezeWithdraw struct {
UnfreezeID string `protobuf:"bytes,1,opt,name=unfreezeID" json:"unfreezeID,omitempty"`
AvailableAmount int64 `protobuf:"varint,2,opt,name=availableAmount" json:"availableAmount,omitempty"`
}
func (m *ReplyQueryUnfreezeWithdraw) Reset() { *m = ReplyQueryUnfreezeWithdraw{} }
func (m *ReplyQueryUnfreezeWithdraw) String() string { return proto.CompactTextString(m) }
func (*ReplyQueryUnfreezeWithdraw) ProtoMessage() {}
func (*ReplyQueryUnfreezeWithdraw) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
func (m *ReplyQueryUnfreezeWithdraw) GetUnfreezeID() string {
if m != nil {
return m.UnfreezeID
}
return ""
}
func (m *ReplyQueryUnfreezeWithdraw) GetAvailableAmount() int64 {
if m != nil {
return m.AvailableAmount
}
return 0
}
func init() {
proto.RegisterType((*Unfreeze)(nil), "types.Unfreeze")
proto.RegisterType((*FixAmount)(nil), "types.FixAmount")
proto.RegisterType((*LeftProportion)(nil), "types.LeftProportion")
proto.RegisterType((*UnfreezeAction)(nil), "types.UnfreezeAction")
proto.RegisterType((*UnfreezeCreate)(nil), "types.UnfreezeCreate")
proto.RegisterType((*UnfreezeWithdraw)(nil), "types.UnfreezeWithdraw")
proto.RegisterType((*UnfreezeTerminate)(nil), "types.UnfreezeTerminate")
proto.RegisterType((*ReceiptUnfreeze)(nil), "types.ReceiptUnfreeze")
proto.RegisterType((*ReplyQueryUnfreezeWithdraw)(nil), "types.ReplyQueryUnfreezeWithdraw")
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// Client API for Unfreeze service
type UnfreezeClient interface {
GetUnfreezeWithdraw(ctx context.Context, in *types1.ReqString, opts ...grpc.CallOption) (*ReplyQueryUnfreezeWithdraw, error)
QueryUnfreeze(ctx context.Context, in *types1.ReqString, opts ...grpc.CallOption) (*Unfreeze, error)
}
type unfreezeClient struct {
cc *grpc.ClientConn
}
func NewUnfreezeClient(cc *grpc.ClientConn) UnfreezeClient {
return &unfreezeClient{cc}
}
func (c *unfreezeClient) GetUnfreezeWithdraw(ctx context.Context, in *types1.ReqString, opts ...grpc.CallOption) (*ReplyQueryUnfreezeWithdraw, error) {
out := new(ReplyQueryUnfreezeWithdraw)
err := grpc.Invoke(ctx, "/types.unfreeze/GetUnfreezeWithdraw", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *unfreezeClient) QueryUnfreeze(ctx context.Context, in *types1.ReqString, opts ...grpc.CallOption) (*Unfreeze, error) {
out := new(Unfreeze)
err := grpc.Invoke(ctx, "/types.unfreeze/QueryUnfreeze", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for Unfreeze service
type UnfreezeServer interface {
GetUnfreezeWithdraw(context.Context, *types1.ReqString) (*ReplyQueryUnfreezeWithdraw, error)
QueryUnfreeze(context.Context, *types1.ReqString) (*Unfreeze, error)
}
func RegisterUnfreezeServer(s *grpc.Server, srv UnfreezeServer) {
s.RegisterService(&_Unfreeze_serviceDesc, srv)
}
func _Unfreeze_GetUnfreezeWithdraw_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(types1.ReqString)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UnfreezeServer).GetUnfreezeWithdraw(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/types.unfreeze/GetUnfreezeWithdraw",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UnfreezeServer).GetUnfreezeWithdraw(ctx, req.(*types1.ReqString))
}
return interceptor(ctx, in, info, handler)
}
func _Unfreeze_QueryUnfreeze_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(types1.ReqString)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UnfreezeServer).QueryUnfreeze(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/types.unfreeze/QueryUnfreeze",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UnfreezeServer).QueryUnfreeze(ctx, req.(*types1.ReqString))
}
return interceptor(ctx, in, info, handler)
}
var _Unfreeze_serviceDesc = grpc.ServiceDesc{
ServiceName: "types.unfreeze",
HandlerType: (*UnfreezeServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetUnfreezeWithdraw",
Handler: _Unfreeze_GetUnfreezeWithdraw_Handler,
},
{
MethodName: "QueryUnfreeze",
Handler: _Unfreeze_QueryUnfreeze_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "unfreeze.proto",
}
func init() { proto.RegisterFile("unfreeze.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 607 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xcb, 0x6e, 0xd3, 0x40,
0x14, 0x8d, 0x93, 0x26, 0xb1, 0x6f, 0x68, 0x5a, 0x86, 0x97, 0x55, 0x21, 0x14, 0x0c, 0x8b, 0xb0,
0x29, 0x28, 0x05, 0x09, 0x89, 0x05, 0x6a, 0xcb, 0x23, 0x48, 0x15, 0x8f, 0x69, 0x11, 0xeb, 0x89,
0x7b, 0xd3, 0x8e, 0x64, 0xcf, 0x98, 0xf1, 0xb8, 0xad, 0xf9, 0x08, 0x7e, 0x80, 0xef, 0x61, 0xc5,
0x4f, 0x21, 0x8f, 0x1f, 0x49, 0x9c, 0x96, 0x88, 0x2e, 0xe7, 0x9c, 0x7b, 0xce, 0xbd, 0x93, 0x7b,
0x3c, 0x81, 0x7e, 0x22, 0xa6, 0x0a, 0xf1, 0x07, 0x6e, 0x47, 0x4a, 0x6a, 0x49, 0xda, 0x3a, 0x8d,
0x30, 0xde, 0xba, 0xe1, 0xcb, 0x30, 0x94, 0x22, 0x07, 0xbd, 0x5f, 0x2d, 0xb0, 0xbf, 0x16, 0x75,
0xe4, 0x01, 0x40, 0xa9, 0xf9, 0xf0, 0xc6, 0xb5, 0x06, 0xd6, 0xd0, 0xa1, 0x73, 0x08, 0xb9, 0x0f,
0x4e, 0xac, 0x99, 0xd2, 0x47, 0x3c, 0x44, 0xb7, 0x39, 0xb0, 0x86, 0x2d, 0x3a, 0x03, 0x32, 0x96,
0xc5, 0x31, 0xea, 0xb7, 0x17, 0xe8, 0xbb, 0x2d, 0x23, 0x9e, 0x01, 0x64, 0x00, 0x3d, 0x73, 0x38,
0x4c, 0xc3, 0x89, 0x0c, 0xdc, 0x35, 0xc3, 0xcf, 0x43, 0x59, 0x77, 0x2d, 0x35, 0x0b, 0xf6, 0x65,
0x22, 0xb4, 0xdb, 0x36, 0xf6, 0x73, 0x48, 0xe6, 0xcf, 0x05, 0xd7, 0x9c, 0x69, 0xa9, 0xdc, 0x4e,
0xee, 0x5f, 0x01, 0x99, 0xff, 0x04, 0x05, 0x4e, 0xb9, 0xcf, 0x99, 0x4a, 0xdd, 0x6e, 0xee, 0x3f,
0x07, 0x65, 0x7a, 0x85, 0x21, 0xe3, 0x82, 0x8b, 0x13, 0xd7, 0xce, 0xa7, 0xaf, 0x00, 0x72, 0x1b,
0xda, 0x21, 0x32, 0x11, 0xbb, 0x8e, 0x51, 0xe6, 0x07, 0xf2, 0x0c, 0x9c, 0x29, 0xbf, 0xd8, 0x0d,
0xcd, 0x48, 0x30, 0xb0, 0x86, 0xbd, 0xd1, 0xe6, 0xb6, 0xf9, 0x1d, 0xb7, 0xdf, 0x95, 0xf8, 0xb8,
0x41, 0x67, 0x45, 0xe4, 0x35, 0xf4, 0x03, 0x9c, 0xea, 0xcf, 0x4a, 0x46, 0x52, 0x69, 0x2e, 0x85,
0xdb, 0x33, 0xb2, 0x3b, 0x85, 0xec, 0x60, 0x81, 0x1c, 0x37, 0x68, 0xad, 0x7c, 0x0f, 0xc0, 0x36,
0xbd, 0x3f, 0x45, 0xda, 0x7b, 0x05, 0x4e, 0xd5, 0x86, 0xdc, 0x85, 0x4e, 0x84, 0x8a, 0xcb, 0x63,
0xb3, 0x99, 0x16, 0x2d, 0x4e, 0x19, 0xce, 0xf2, 0x01, 0xf3, 0x95, 0x14, 0x27, 0xef, 0x23, 0xf4,
0x17, 0x9b, 0x5d, 0xe9, 0xf0, 0x18, 0xd6, 0x35, 0x8a, 0xa3, 0x53, 0x99, 0xc4, 0x4c, 0x1c, 0xeb,
0xd3, 0xc2, 0x68, 0x11, 0xf4, 0xfe, 0x58, 0xd0, 0x2f, 0xa3, 0xb2, 0xeb, 0x1b, 0xc3, 0xa7, 0xd0,
0xf1, 0x15, 0x32, 0x8d, 0xc6, 0x70, 0x76, 0xc9, 0xb2, 0x6c, 0xdf, 0x90, 0xe3, 0x06, 0x2d, 0xca,
0xc8, 0x0b, 0xb0, 0xcf, 0xb9, 0x3e, 0x3d, 0x56, 0xec, 0xdc, 0x34, 0xe9, 0x8d, 0xee, 0xd5, 0x24,
0xdf, 0x0a, 0x7a, 0xdc, 0xa0, 0x55, 0x29, 0x79, 0x09, 0x8e, 0x46, 0x15, 0x72, 0x91, 0xb5, 0x6a,
0x19, 0x9d, 0x5b, 0xd3, 0x1d, 0x95, 0x7c, 0xb6, 0x8e, 0xaa, 0x98, 0xf4, 0xa1, 0xa9, 0x53, 0x93,
0xb6, 0x36, 0x6d, 0xea, 0x74, 0xaf, 0x0b, 0xed, 0x33, 0x16, 0x24, 0xe8, 0xfd, 0x6e, 0xce, 0x6e,
0x93, 0x8f, 0xb9, 0x18, 0x6f, 0xeb, 0x9f, 0xf1, 0x6e, 0xae, 0x88, 0x77, 0x6b, 0x55, 0xbc, 0xd7,
0x96, 0xe2, 0x5d, 0x0b, 0x70, 0x7b, 0x39, 0xc0, 0x55, 0x44, 0x3b, 0x57, 0x46, 0xb4, 0x7b, 0xbd,
0x88, 0xda, 0xd7, 0x8f, 0xe8, 0x08, 0x36, 0xeb, 0xab, 0x5b, 0xf5, 0x8e, 0x78, 0x3b, 0x70, 0x73,
0x69, 0x6d, 0x2b, 0x45, 0x0c, 0x36, 0x28, 0xfa, 0xc8, 0x23, 0x5d, 0xbd, 0x57, 0x8f, 0x60, 0x2d,
0x52, 0x78, 0x56, 0x84, 0x6f, 0xa3, 0x96, 0x08, 0x6a, 0x48, 0xf2, 0x04, 0xba, 0x7e, 0xa2, 0x14,
0x16, 0xdf, 0xc7, 0x25, 0x75, 0x25, 0xef, 0x4d, 0x61, 0x8b, 0x62, 0x14, 0xa4, 0x5f, 0x12, 0x54,
0xe9, 0xff, 0xde, 0x8a, 0x0c, 0x61, 0x83, 0x9d, 0x31, 0x1e, 0xb0, 0x49, 0x80, 0xbb, 0xf3, 0x1f,
0x64, 0x1d, 0x1e, 0xfd, 0xb4, 0xc0, 0x2e, 0x85, 0xe4, 0x00, 0x6e, 0xbd, 0x47, 0xbd, 0xd4, 0xad,
0xdc, 0x21, 0xc5, 0xef, 0x87, 0x5a, 0x71, 0x71, 0xb2, 0xf5, 0xb0, 0x42, 0xae, 0x1a, 0xd1, 0x6b,
0x90, 0xe7, 0xb0, 0xbe, 0x40, 0x5d, 0xe2, 0x53, 0xbf, 0xbf, 0xd7, 0x98, 0x74, 0xcc, 0x9f, 0xc1,
0xce, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x42, 0x46, 0xd7, 0x7c, 0x33, 0x06, 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