Commit 96ecc075 authored by 张振华's avatar 张振华

update

parent f94e04d5
// 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 main
import (
"io/ioutil"
"os"
"time"
"fmt"
"github.com/33cn/chain33/common"
drivers "github.com/33cn/chain33/system/store"
"github.com/33cn/chain33/types"
kvm "github.com/33cn/plugin/plugin/store/kvmvcc"
)
const MaxKeylenth int = 64
func newStoreCfg(dir string) *types.Store {
return &types.Store{Name: "kvmvcc_test", Driver: "leveldb", DbPath: dir, DbCache: 100}
}
func GetRandomString(length int) string {
return common.GetRandPrintString(20, length)
}
func main() {
dir, _ := ioutil.TempDir("", "kvmvcc")
//defer os.RemoveAll(dir) // clean up
os.RemoveAll(dir) //删除已存在目录
var storeCfg = newStoreCfg(dir)
store := kvm.New(storeCfg, nil).(*kvm.KVMVCCStore)
var kv []*types.KeyValue
var key string
var value string
var keys [][]byte
for i := 0; i < 20; i++ {
key = GetRandomString(MaxKeylenth)
value = fmt.Sprintf("vabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst%d", i)
keys = append(keys, []byte(string(key)))
kv = append(kv, &types.KeyValue{Key: []byte(string(key)), Value: []byte(string(value))})
}
datas := &types.StoreSet{
StateHash: drivers.EmptyRoot[:],
KV: kv,
Height: 0}
var hashes [][]byte
blocks := 50000
times := 10000
start1 := time.Now()
for i := 0; i < blocks; i++ {
datas.Height = int64(i)
value = fmt.Sprintf("vvabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst%d", i)
for j := 0; j < 20; j++ {
datas.KV[j].Value = []byte(value)
}
hash, err := store.MemSet(datas, true)
if err != nil {
fmt.Println("MemSet failed", err)
}
req := &types.ReqHash{
Hash: hash,
}
_, err = store.Commit(req)
if err != nil {
fmt.Println("Commit failed", err)
}
datas.StateHash = hash
if i < times {
hashes = append(hashes, hash)
}
fmt.Println("Block number:", i)
}
end1 := time.Now()
start := time.Now()
getData := &types.StoreGet{
StateHash: hashes[0],
Keys: keys}
for i := 0; i < times; i++ {
getData.StateHash = hashes[i]
store.Get(getData)
fmt.Println("read times:", i, " kv numbers:", i * 20)
}
end := time.Now()
fmt.Println("kvmvcc BenchmarkStoreGetKvsFor100million MemSet&Commit cost time is ", end1.Sub(start1), "blocks is", blocks)
fmt.Println("kvmvcc BenchmarkStoreGetKvsFor100million Get cost time is", end.Sub(start), "num is ", times, ",blocks is ", blocks)
}
// 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 main
import (
"io/ioutil"
"os"
"time"
"fmt"
"github.com/33cn/chain33/common"
drivers "github.com/33cn/chain33/system/store"
"github.com/33cn/chain33/types"
mavl "github.com/33cn/chain33/system/store/mavl"
)
const MaxKeylenth int = 64
func newStoreCfg(dir string) *types.Store {
return &types.Store{Name: "mavl_test", Driver: "leveldb", DbPath: dir, DbCache: 100}
}
func GetRandomString(length int) string {
return common.GetRandPrintString(20, length)
}
func main() {
dir, _ := ioutil.TempDir("", "mavl")
//defer os.RemoveAll(dir) // clean up
os.RemoveAll(dir) //删除已存在目录
var storeCfg = newStoreCfg(dir)
store := mavl.New(storeCfg, nil).(*mavl.Store)
var kv []*types.KeyValue
var key string
var value string
var keys [][]byte
for i := 0; i < 20; i++ {
key = GetRandomString(MaxKeylenth)
value = fmt.Sprintf("vabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst%d", i)
keys = append(keys, []byte(string(key)))
kv = append(kv, &types.KeyValue{Key: []byte(string(key)), Value: []byte(string(value))})
}
datas := &types.StoreSet{
StateHash: drivers.EmptyRoot[:],
KV: kv,
Height: 0}
var hashes [][]byte
blocks := 50000
times := 10000
start1 := time.Now()
for i := 0; i < blocks; i++ {
datas.Height = int64(i)
value = fmt.Sprintf("vvabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst%d", i)
for j := 0; j < 20; j++ {
datas.KV[j].Value = []byte(value)
}
hash, err := store.MemSet(datas, true)
if err != nil {
fmt.Println("MemSet failed", err)
}
req := &types.ReqHash{
Hash: hash,
}
_, err = store.Commit(req)
if err != nil {
fmt.Println("Commit failed", err)
}
datas.StateHash = hash
if i < times {
hashes = append(hashes, hash)
}
fmt.Println("Block number:", i)
}
end1 := time.Now()
start := time.Now()
getData := &types.StoreGet{
StateHash: hashes[0],
Keys: keys}
for i := 0; i < times; i++ {
getData.StateHash = hashes[i]
store.Get(getData)
fmt.Println("read times:", i, " kv numbers:", i * 20)
}
end := time.Now()
fmt.Println("mavl BenchmarkStoreGetKvsFor100million MemSet&Commit cost time is ", end1.Sub(start1), "blocks is", blocks)
fmt.Println("mavl BenchmarkStoreGetKvsFor100million Get cost time is", end.Sub(start), "num is ", times, ",blocks is ", blocks)
}
// 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 main
import (
"io/ioutil"
"os"
"time"
"fmt"
"github.com/33cn/chain33/common"
drivers "github.com/33cn/chain33/system/store"
"github.com/33cn/chain33/types"
mpt "github.com/33cn/plugin/plugin/store/mpt"
)
const MaxKeylenth int = 64
func newStoreCfg(dir string) *types.Store {
return &types.Store{Name: "mpt_test", Driver: "leveldb", DbPath: dir, DbCache: 100}
}
func GetRandomString(length int) string {
return common.GetRandPrintString(20, length)
}
func main() {
dir, _ := ioutil.TempDir("", "mpt")
//defer os.RemoveAll(dir) // clean up
os.RemoveAll(dir) //删除已存在目录
var storeCfg = newStoreCfg(dir)
store := mpt.New(storeCfg, nil).(*mpt.Store)
var kv []*types.KeyValue
var key string
var value string
var keys [][]byte
for i := 0; i < 20; i++ {
key = GetRandomString(MaxKeylenth)
value = fmt.Sprintf("vabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst%d", i)
keys = append(keys, []byte(string(key)))
kv = append(kv, &types.KeyValue{Key: []byte(string(key)), Value: []byte(string(value))})
}
datas := &types.StoreSet{
StateHash: drivers.EmptyRoot[:],
KV: kv,
Height: 0}
var hashes [][]byte
blocks := 50000
times := 10000
start1 := time.Now()
for i := 0; i < blocks; i++ {
datas.Height = int64(i)
value = fmt.Sprintf("vvabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst%d", i)
for j := 0; j < 20; j++ {
datas.KV[j].Value = []byte(value)
}
hash, err := store.MemSet(datas, true)
if err != nil {
fmt.Println("MemSet failed", err)
}
req := &types.ReqHash{
Hash: hash,
}
_, err = store.Commit(req)
if err != nil {
fmt.Println("Commit failed", err)
}
datas.StateHash = hash
if i < times {
hashes = append(hashes, hash)
}
fmt.Println("Block number:", i)
}
end1 := time.Now()
start := time.Now()
getData := &types.StoreGet{
StateHash: hashes[0],
Keys: keys}
for i := 0; i < times; i++ {
getData.StateHash = hashes[i]
store.Get(getData)
fmt.Println("read times:", i, " kv numbers:", i * 20)
}
end := time.Now()
fmt.Println("mpt BenchmarkStoreGetKvsFor100million MemSet&Commit cost time is ", end1.Sub(start1), "blocks is", blocks)
fmt.Println("mpt BenchmarkStoreGetKvsFor100million Get cost time is", end.Sub(start), "num is ", times, ",blocks is ", blocks)
}
...@@ -100,6 +100,7 @@ timeoutWaitNotify=2000 ...@@ -100,6 +100,7 @@ timeoutWaitNotify=2000
createEmptyBlocks=false createEmptyBlocks=false
createEmptyBlocksInterval=0 createEmptyBlocksInterval=0
validatorNodes=["127.0.0.1:46656"] validatorNodes=["127.0.0.1:46656"]
delegateNum=3
blockInterval=3 blockInterval=3
continueBlockNum=12 continueBlockNum=12
isValidator=false isValidator=false
......
...@@ -18,7 +18,7 @@ import ( ...@@ -18,7 +18,7 @@ import (
ttypes "github.com/33cn/plugin/plugin/consensus/dpos/types" ttypes "github.com/33cn/plugin/plugin/consensus/dpos/types"
) )
const tendermintVersion = "0.1.0" const dposVersion = "0.1.0"
var ( var (
dposlog = log15.New("module", "dpos") dposlog = log15.New("module", "dpos")
...@@ -38,6 +38,7 @@ var ( ...@@ -38,6 +38,7 @@ var (
dposCycle = dposDelegateNum * dposBlockInterval * dposContinueBlockNum dposCycle = dposDelegateNum * dposBlockInterval * dposContinueBlockNum
dposPeriod = dposBlockInterval * dposContinueBlockNum dposPeriod = dposBlockInterval * dposContinueBlockNum
zeroHash [32]byte zeroHash [32]byte
dposPort string = "36656"
) )
func init() { func init() {
...@@ -70,9 +71,11 @@ type subConfig struct { ...@@ -70,9 +71,11 @@ type subConfig struct {
CreateEmptyBlocks bool `json:"createEmptyBlocks"` CreateEmptyBlocks bool `json:"createEmptyBlocks"`
CreateEmptyBlocksInterval int32 `json:"createEmptyBlocksInterval"` CreateEmptyBlocksInterval int32 `json:"createEmptyBlocksInterval"`
ValidatorNodes []string `json:"validatorNodes"` ValidatorNodes []string `json:"validatorNodes"`
DelegateNum int64 `json:"delegateNum"`
BlockInterval int64 `json:"blockInterval"` BlockInterval int64 `json:"blockInterval"`
ContinueBlockNum int64 `json:"continueBlockNum"` ContinueBlockNum int64 `json:"continueBlockNum"`
IsValidator bool `json:"isValidator"` IsValidator bool `json:"isValidator"`
Port string `json:"port"`
} }
func (client *Client) applyConfig(sub []byte) { func (client *Client) applyConfig(sub []byte) {
...@@ -100,9 +103,13 @@ func (client *Client) applyConfig(sub []byte) { ...@@ -100,9 +103,13 @@ func (client *Client) applyConfig(sub []byte) {
createEmptyBlocksInterval = subcfg.CreateEmptyBlocksInterval createEmptyBlocksInterval = subcfg.CreateEmptyBlocksInterval
} }
if subcfg.DelegateNum > 0 {
dposDelegateNum = subcfg.DelegateNum
}
if len(subcfg.ValidatorNodes) > 0 { if len(subcfg.ValidatorNodes) > 0 {
validatorNodes = subcfg.ValidatorNodes validatorNodes = subcfg.ValidatorNodes
dposDelegateNum = int64(len(subcfg.ValidatorNodes)) //dposDelegateNum = int64(len(subcfg.ValidatorNodes))
} }
if subcfg.BlockInterval > 0 { if subcfg.BlockInterval > 0 {
...@@ -113,6 +120,9 @@ func (client *Client) applyConfig(sub []byte) { ...@@ -113,6 +120,9 @@ func (client *Client) applyConfig(sub []byte) {
dposContinueBlockNum = subcfg.ContinueBlockNum dposContinueBlockNum = subcfg.ContinueBlockNum
} }
if subcfg.Port != "" {
dposPort = subcfg.Port
}
dposCycle = dposDelegateNum * dposBlockInterval * dposContinueBlockNum dposCycle = dposDelegateNum * dposBlockInterval * dposContinueBlockNum
dposPeriod = dposBlockInterval * dposContinueBlockNum dposPeriod = dposBlockInterval * dposContinueBlockNum
...@@ -137,7 +147,8 @@ func New(cfg *types.Consensus, sub []byte) queue.Module { ...@@ -137,7 +147,8 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
//return nil //return nil
} }
cr, err := crypto.New(types.GetSignName("", types.ED25519)) //为了使用VRF,需要使用SECP256K1体系的公私钥
cr, err := crypto.New(types.GetSignName("", types.SECP256K1))
if err != nil { if err != nil {
dposlog.Error("NewDPosClient", "err", err) dposlog.Error("NewDPosClient", "err", err)
return nil return nil
...@@ -145,7 +156,15 @@ func New(cfg *types.Consensus, sub []byte) queue.Module { ...@@ -145,7 +156,15 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
ttypes.ConsensusCrypto = cr ttypes.ConsensusCrypto = cr
priv, err := cr.GenKey() //安全连接仍然要使用ed25519
cr2, err := crypto.New(types.GetSignName("", types.ED25519))
if err != nil {
dposlog.Error("NewDPosClient", "err", err)
return nil
}
ttypes.SecureConnCrypto = cr2
priv, err := cr2.GenKey()
if err != nil { if err != nil {
dposlog.Error("NewDPosClient", "GenKey err", err) dposlog.Error("NewDPosClient", "GenKey err", err)
return nil return nil
...@@ -262,8 +281,8 @@ OuterLoop: ...@@ -262,8 +281,8 @@ OuterLoop:
csState.SetPrivValidator(client.privValidator, client.ValidatorIndex()) csState.SetPrivValidator(client.privValidator, client.ValidatorIndex())
// Create & add listener // Create & add listener
protocol, listeningAddress := "tcp", "0.0.0.0:36656" protocol, listeningAddress := "tcp", "0.0.0.0:" + dposPort
node := NewNode(validatorNodes, protocol, listeningAddress, client.privKey, valMgr.ChainID, tendermintVersion, csState) node := NewNode(validatorNodes, protocol, listeningAddress, client.privKey, valMgr.ChainID, dposVersion, csState)
client.node = node client.node = node
......
...@@ -301,11 +301,11 @@ func shareAuthSignature(sc io.ReadWriter, pubKey crypto.PubKey, signature crypto ...@@ -301,11 +301,11 @@ func shareAuthSignature(sc io.ReadWriter, pubKey crypto.PubKey, signature crypto
//n := int(0) // not used. //n := int(0) // not used.
//recvMsg = wire.ReadBinary(authSigMessage{}, bytes.NewBuffer(readBuffer), authSigMsgSize, &n, &err2).(authSigMessage) //recvMsg = wire.ReadBinary(authSigMessage{}, bytes.NewBuffer(readBuffer), authSigMsgSize, &n, &err2).(authSigMessage)
//secret.Info("shareAuthSignature", "readBuffer", readBuffer) //secret.Info("shareAuthSignature", "readBuffer", readBuffer)
recvMsg.Key, err2 = types.ConsensusCrypto.PubKeyFromBytes(readBuffer[:32]) recvMsg.Key, err2 = types.SecureConnCrypto.PubKeyFromBytes(readBuffer[:32])
if err2 != nil { if err2 != nil {
return return
} }
recvMsg.Sig, err2 = types.ConsensusCrypto.SignatureFromBytes(readBuffer[32:]) recvMsg.Sig, err2 = types.SecureConnCrypto.SignatureFromBytes(readBuffer[32:])
if err2 != nil { if err2 != nil {
return return
} }
......
...@@ -252,8 +252,8 @@ func (pv *PrivValidatorImp) save() { ...@@ -252,8 +252,8 @@ func (pv *PrivValidatorImp) save() {
Address: addr, Address: addr,
LastSignature: nil, LastSignature: nil,
} }
privValFS.PrivKey = KeyText{Kind: "ed25519", Data: Fmt("%X", pv.PrivKey.Bytes()[:])} privValFS.PrivKey = KeyText{Kind: "secp256k1", Data: Fmt("%X", pv.PrivKey.Bytes()[:])}
privValFS.PubKey = KeyText{Kind: "ed25519", Data: pv.PubKey.KeyString()} privValFS.PubKey = KeyText{Kind: "secp256k1", Data: pv.PubKey.KeyString()}
if len(pv.LastSignBytes) != 0 { if len(pv.LastSignBytes) != 0 {
tmp := Fmt("%X", pv.LastSignBytes[:]) tmp := Fmt("%X", pv.LastSignBytes[:])
privValFS.LastSignBytes = tmp privValFS.LastSignBytes = tmp
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"github.com/33cn/chain33/common/address"
"io" "io"
"time" "time"
...@@ -30,6 +31,7 @@ var ( ...@@ -30,6 +31,7 @@ var (
votelog = log15.New("module", "tendermint-vote") votelog = log15.New("module", "tendermint-vote")
ConsensusCrypto crypto.Crypto ConsensusCrypto crypto.Crypto
SecureConnCrypto crypto.Crypto
) )
// Signable is an interface for all signable things. // Signable is an interface for all signable things.
...@@ -102,7 +104,7 @@ func (vote *Vote) String() string { ...@@ -102,7 +104,7 @@ func (vote *Vote) String() string {
// Verify ... // Verify ...
func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error { func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error {
addr := GenAddressByPubKey(pubKey) addr := address.PubKeyToAddress(pubKey.Bytes()).Hash160[:]
if !bytes.Equal(addr, vote.VoterNodeAddress) { if !bytes.Equal(addr, vote.VoterNodeAddress) {
return ErrVoteInvalidValidatorAddress return ErrVoteInvalidValidatorAddress
} }
...@@ -189,7 +191,7 @@ func (notify *Notify) String() string { ...@@ -189,7 +191,7 @@ func (notify *Notify) String() string {
// Verify ... // Verify ...
func (notify *Notify) Verify(chainID string, pubKey crypto.PubKey) error { func (notify *Notify) Verify(chainID string, pubKey crypto.PubKey) error {
addr := GenAddressByPubKey(pubKey) addr := address.PubKeyToAddress(pubKey.Bytes()).Hash160[:]
if !bytes.Equal(addr, notify.NotifyNodeAddress) { if !bytes.Equal(addr, notify.NotifyNodeAddress) {
return ErrNotifyInvalidValidatorAddress return ErrNotifyInvalidValidatorAddress
} }
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/33cn/chain33/common/address"
"math/rand" "math/rand"
ttypes "github.com/33cn/plugin/plugin/consensus/dpos/types" ttypes "github.com/33cn/plugin/plugin/consensus/dpos/types"
...@@ -85,7 +86,7 @@ func MakeGenesisValidatorMgr(genDoc *ttypes.GenesisDoc) (ValidatorMgr, error) { ...@@ -85,7 +86,7 @@ func MakeGenesisValidatorMgr(genDoc *ttypes.GenesisDoc) (ValidatorMgr, error) {
// Make validator // Make validator
validators[i] = &ttypes.Validator{ validators[i] = &ttypes.Validator{
Address: ttypes.GenAddressByPubKey(pubKey), Address: address.PubKeyToAddress(pubKey.Bytes()).Hash160[:],
PubKey: pubKey.Bytes(), PubKey: pubKey.Bytes(),
} }
} }
......
all:
chmod +x ./build.sh
./build.sh $(OUT) $(FLAG)
\ No newline at end of file
#!/usr/bin/env bash
strpwd=$(pwd)
strcmd=${strpwd##*dapp/}
strapp=${strcmd%/cmd*}
OUT_DIR="${1}/$strapp"
#FLAG=$2
mkdir -p "${OUT_DIR}"
cp ./build/* "${OUT_DIR}"
OUT_TESTDIR="${1}/dapptest/$strapp"
mkdir -p "${OUT_TESTDIR}"
chmod +x ./build/test-rpc.sh
cp ./build/test-rpc.sh "${OUT_TESTDIR}"
This diff is collapsed.
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
/*
该合约主要是配合Dpos共识,完成(1)候选节点的注册、去注册、投票及查询管理。(2)Dpos共识运行过程中,得票数TopN(N为约定的受托节点数量)受托节点的VRF相关信息的分阶段发布管理。
(1)系统初始运行时,会有默认的几个受托节点进行共识运行。
(2)系统运行后,可以重新选举受托节点,各个候选节点需要抵押10000个币(暂未实现),注册成为候选节点。
(3)候选节点可以在社区宣传,让大家为自己投票。
(4)用户可以为自己支持的候选节点投票。投票后,资金会冻结,3天以后才可以撤销投票。
(5)系统运行过程中,每到固定区块高度时(比如10万个区块),重新获取当前投票数据,并确定下一个时间段的受托节点。
(6)受托节点进行共识出块,每个cycle(一个cycle中,各个受托节点轮番出块,直到都轮一遍)分两个阶段进行VRF信息发布:
第一个阶段,各个受托节点发布自己的VRF的M信息
第二个阶段,各个受托节点发布自己的VRF的R、P信息
上述VRF的M、R、P可以验证。
(7)新的cycle中,使用上述VRF信息进行受托节点的出块顺序的重新洗牌,按洗牌结果决定各受托节点出块的顺序
*/
// 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"
dty "github.com/33cn/plugin/plugin/dapp/dposvote/types"
)
var logger = log.New("module", "execs.dposvote")
var driverName = dty.DPosX
var (
dposDelegateNum int64 = 3 //委托节点个数,从配置读取,以后可以根据投票结果来定
dposBlockInterval int64 = 3 //出块间隔,当前按3s
dposContinueBlockNum int64 = 6 //一个委托节点当选后,一次性持续出块数量
dposCycle = dposDelegateNum * dposBlockInterval * dposContinueBlockNum
dposPeriod = dposBlockInterval * dposContinueBlockNum
)
type CycleInfo struct {
cycle int64
cycleStart int64
cycleStop int64
}
func calcCycleByTime(now int64) *CycleInfo {
cycle := now / dposCycle
cycleStart := now - now % dposCycle
cycleStop := cycleStart + dposCycle - 1
return &CycleInfo{
cycle: cycle,
cycleStart: cycleStart,
cycleStop: cycleStop,
}
}
func init() {
ety := types.LoadExecutorType(driverName)
ety.InitFuncList(types.ListMethod(&DPos{}))
}
// Init DPos Executor
func Init(name string, sub []byte) {
driverName := GetName()
if name != driverName {
panic("system dapp can't be rename")
}
drivers.Register(driverName, newDposVote, types.GetDappFork(driverName, "Enable"))
//读取一下配置项,用于和共识模块一致计算cycle
dposDelegateNum = types.Conf("config.consensus.sub.dpos").GInt("delegateNum")
dposBlockInterval = types.Conf("config.consensus.sub.dpos").GInt("blockInterval")
dposContinueBlockNum = types.Conf("config.consensus.sub.dpos").GInt("continueBlockNum")
dposCycle = dposDelegateNum * dposBlockInterval * dposContinueBlockNum
dposPeriod = dposBlockInterval * dposContinueBlockNum
}
//DPos 执行器,用于Dpos候选节点注册、投票,VRF信息注册管理等功能
type DPos struct {
drivers.DriverBase
}
func newDposVote() drivers.Driver {
t := &DPos{}
t.SetChild(t)
t.SetExecutorType(types.LoadExecutorType(driverName))
return t
}
//GetName 获取DPos执行器的名称
func GetName() string {
return newDposVote().GetName()
}
//ExecutorOrder Exec 的时候 同时执行 ExecLocal
func (g *DPos) ExecutorOrder() int64 {
return drivers.ExecLocalSameTime
}
//GetDriverName 获取DPos执行器的名称
func (g *DPos) GetDriverName() string {
return dty.DPosX
}
// CheckReceiptExecOk return true to check if receipt ty is ok
func (g *DPos) CheckReceiptExecOk() bool {
return true
}
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"
dty "github.com/33cn/plugin/plugin/dapp/dposvote/types"
)
//Exec_Regist DPos执行器注册候选节点
func (d *DPos) Exec_Regist(payload *dty.DposCandidatorRegist, tx *types.Transaction, index int) (*types.Receipt, error) {
action := NewAction(d, tx, index)
return action.Regist(payload)
}
//Exec_CancelRegist DPos执行器取消注册候选节点
func (d *DPos) Exec_CancelRegist(payload *dty.DposCandidatorCancelRegist, tx *types.Transaction, index int) (*types.Receipt, error) {
action := NewAction(d, tx, index)
return action.CancelRegist(payload)
}
//Exec_ReRegist DPos执行器重新注册候选节点
func (d *DPos) Exec_ReRegist(payload *dty.DposCandidatorRegist, tx *types.Transaction, index int) (*types.Receipt, error) {
action := NewAction(d, tx, index)
return action.ReRegist(payload)
}
//Exec_Vote DPos执行器为候选节点投票
func (d *DPos) Exec_Vote(payload *dty.DposVote, tx *types.Transaction, index int) (*types.Receipt, error) {
action := NewAction(d, tx, index)
return action.Vote(payload)
}
//Exec_CancelVote DPos执行器撤销对一个候选节点的投票
func (d *DPos) Exec_CancelVote(payload *dty.DposCancelVote, tx *types.Transaction, index int) (*types.Receipt, error) {
action := NewAction(d, tx, index)
return action.CancelVote(payload)
}
//Exec_RegistVrfM DPos执行器注册一个受托节点的Vrf M信息
func (d *DPos) Exec_RegistVrfM(payload *dty.DposVrfMRegist, tx *types.Transaction, index int) (*types.Receipt, error) {
action := NewAction(d, tx, index)
return action.RegistVrfM(payload)
}
//Exec_RegistVrfRP DPos执行器注册一个受托节点的Vrf R/P信息
func (d *DPos) Exec_RegistVrfRP(payload *dty.DposVrfRPRegist, tx *types.Transaction, index int) (*types.Receipt, error) {
action := NewAction(d, tx, index)
return action.RegistVrfRP(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 (
"fmt"
"github.com/33cn/chain33/types"
dty "github.com/33cn/plugin/plugin/dapp/dposvote/types"
)
func (d *DPos) rollbackCand(cand *dty.CandidatorInfo, log *dty.ReceiptCandicator) {
if cand == nil || log == nil {
return
}
//如果状态发生了变化,则需要将状态恢复到前一状态
if log.StatusChange {
cand.Status = log.PreStatus
cand.Index = cand.PreIndex
}
//如果投票了,则需要把投票回滚
if log.Voted {
cand.Votes -= log.Votes
if log.Votes > 0 {
//如果是投票,则回滚时将投票删除。
cand.Voters = cand.Voters[:len(cand.Voters)-1]
} else {
//如果是撤销投票,则回滚时,将删除的投票还回来
voter := &dty.DposVoter{
FromAddr: log.FromAddr,
Pubkey: log.Pubkey,
Votes: -log.Votes,
Index: log.Index,
Time: log.Time - dty.VoteFrozenTime,
}
cand.Voters = append(cand.Voters, voter)
}
}
}
func (d *DPos) rollbackCandVote(log *dty.ReceiptCandicator) (kvs []*types.KeyValue, err error) {
voterTable := dty.NewDposVoteTable(d.GetLocalDB())
candTable := dty.NewDposCandidatorTable(d.GetLocalDB())
if err != nil {
return nil, err
}
if log.Status == dty.CandidatorStatusRegist {
//注册回滚,cand表删除记录
err = candTable.Del(log.Pubkey)
if err != nil {
return nil, err
}
kvs, err = candTable.Save()
return kvs, err
} else if log.Status == dty.CandidatorStatusVoted {
//投票阶段回滚,回滚状态,回滚投票
candInfo := log.CandInfo
log.CandInfo = nil
//先回滚候选节点信息
d.rollbackCand(candInfo, log)
err = candTable.Replace(candInfo)
if err != nil {
return nil, err
}
kvs1, err := candTable.Save()
if err != nil {
return nil, err
}
//删除投票信息
err = voterTable.Del([]byte(fmt.Sprintf("%018d", log.Index)))
if err != nil {
return nil, err
}
kvs2, err := voterTable.Save()
if err != nil {
return nil, err
}
kvs = append(kvs1, kvs2...)
} else if log.Status == dty.CandidatorStatusCancelVoted {
//撤销投票回滚,需要将撤销的投票还回来
candInfo := log.CandInfo
log.CandInfo = nil
//先回滚候选节点信息
d.rollbackCand(candInfo, log)
err = candTable.Replace(candInfo)
if err != nil {
return nil, err
}
kvs1, err := candTable.Save()
if err != nil {
return nil, err
}
//删除投票信息
err = voterTable.Del([]byte(fmt.Sprintf("%018d", log.Index)))
if err != nil {
return nil, err
}
kvs2, err := voterTable.Save()
if err != nil {
return nil, err
}
kvs = append(kvs1, kvs2...)
}
return kvs, nil
}
func (d *DPos) rollbackVrf(log *dty.ReceiptVrf) (kvs []*types.KeyValue, err error) {
if log.Status == dty.VrfStatusMRegist {
vrfMTable := dty.NewDposVrfMTable(d.GetLocalDB())
//注册回滚,cand表删除记录
err = vrfMTable.Del([]byte(fmt.Sprintf("%018d", log.Index)))
if err != nil {
return nil, err
}
kvs, err = vrfMTable.Save()
return kvs, err
} else if log.Status == dty.VrfStatusRPRegist {
VrfRPTable := dty.NewDposVrfRPTable(d.GetLocalDB())
err = VrfRPTable.Del([]byte(fmt.Sprintf("%018d", log.Index)))
if err != nil {
return nil, err
}
kvs, err = VrfRPTable.Save()
return kvs, err
}
return nil, nil
}
func (d *DPos) execDelLocal(receipt *types.ReceiptData) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
if receipt.GetTy() != types.ExecOk {
return dbSet, nil
}
for _, log := range receipt.Logs {
switch log.GetTy() {
case dty.CandidatorStatusRegist, dty.CandidatorStatusVoted, dty.CandidatorStatusCancelVoted, dty.CandidatorStatusCancelRegist:
receiptLog := &dty.ReceiptCandicator{}
if err := types.Decode(log.Log, receiptLog); err != nil {
return nil, err
}
kv, err := d.rollbackCandVote(receiptLog)
if err != nil {
return nil, err
}
dbSet.KV = append(dbSet.KV, kv...)
case dty.VrfStatusMRegist, dty.VrfStatusRPRegist:
receiptLog := &dty.ReceiptVrf{}
if err := types.Decode(log.Log, receiptLog); err != nil {
return nil, err
}
kv, err := d.rollbackVrf(receiptLog)
if err != nil {
return nil, err
}
dbSet.KV = append(dbSet.KV, kv...)
}
}
return dbSet, nil
}
//ExecDelLocal_Regist method
func (d *DPos) ExecDelLocal_Regist(payload *dty.DposCandidatorRegist, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return d.execDelLocal(receiptData)
}
//ExecDelLocal_CancelRegist method
func (d *DPos) ExecDelLocal_CancelRegist(payload *dty.DposCandidatorCancelRegist, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return d.execDelLocal(receiptData)
}
//ExecDelLocal_ReRegist method
func (d *DPos) ExecDelLocal_ReRegist(payload *dty.DposCandidatorRegist, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return d.execDelLocal(receiptData)
}
//ExecDelLocal_Vote method
func (d *DPos) ExecDelLocal_Vote(payload *dty.DposVote, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return d.execDelLocal(receiptData)
}
//ExecDelLocal_CancelVote method
func (d *DPos) ExecDelLocal_CancelVote(payload *dty.DposCancelVote, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return d.execDelLocal(receiptData)
}
//ExecDelLocal_VrfMRegist method
func (d *DPos) ExecDelLocal_VrfMRegist(payload *dty.DposVrfMRegist, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return d.execDelLocal(receiptData)
}
//ExecDelLocal_VrfRPRegist method
func (d *DPos) ExecDelLocal_VrfRPRegist(payload *dty.DposVrfRPRegist, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return d.execDelLocal(receiptData)
}
\ 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 executor
import (
"github.com/33cn/chain33/types"
dty "github.com/33cn/plugin/plugin/dapp/dposvote/types"
)
func (d *DPos) updateCandVote(log *dty.ReceiptCandicator) (kvs []*types.KeyValue, err error) {
voteTable := dty.NewDposVoteTable(d.GetLocalDB())
canTable := dty.NewDposCandidatorTable(d.GetLocalDB())
if log.Status == dty.CandidatorStatusRegist {
candInfo := log.CandInfo
log.CandInfo = nil
err = canTable.Add(candInfo)
if err != nil {
return nil, err
}
kvs, err = canTable.Save()
if err != nil {
return nil, err
}
} else if log.Status == dty.CandidatorStatusVoted {
candInfo := log.CandInfo
log.CandInfo = nil
voter := candInfo.Voters[len(candInfo.Voters)-1]
err = canTable.Replace(candInfo)
if err != nil {
return nil, err
}
kvs1, err := canTable.Save()
if err != nil {
return nil, err
}
err = voteTable.Add(voter)
if err != nil {
return nil, err
}
kvs2, err := voteTable.Save()
if err != nil {
return nil, err
}
kvs = append(kvs1, kvs2...)
} else if log.Status == dty.CandidatorStatusCancelVoted {
candInfo := log.CandInfo
log.CandInfo = nil
voter := &dty.DposVoter{
FromAddr: log.FromAddr,
Pubkey: log.Pubkey,
Votes: log.Votes,
Index: log.Index,
Time: log.Time,
}
err = canTable.Replace(candInfo)
if err != nil {
return nil, err
}
kvs1, err := canTable.Save()
if err != nil {
return nil, err
}
err = voteTable.Add(voter)
if err != nil {
return nil, err
}
kvs2, err := voteTable.Save()
if err != nil {
return nil, err
}
kvs = append(kvs1, kvs2...)
}
return kvs, nil
}
func (d *DPos) updateVrf(log *dty.ReceiptVrf) (kvs []*types.KeyValue, err error) {
if log.Status == dty.VrfStatusMRegist {
vrfMTable := dty.NewDposVrfMTable(d.GetLocalDB())
vrfM := &dty.DposVrfM{
Index: log.Index,
Pubkey: log.Pubkey,
Cycle: log.Cycle,
Height: log.Height,
M: log.M,
Time: log.Time,
}
err = vrfMTable.Add(vrfM)
if err != nil {
return nil, err
}
kvs, err = vrfMTable.Save()
if err != nil {
return nil, err
}
} else if log.Status == dty.VrfStatusRPRegist {
VrfRPTable := dty.NewDposVrfRPTable(d.GetLocalDB())
vrfRP := &dty.DposVrfRP{
Index: log.Index,
Pubkey: log.Pubkey,
Cycle: log.Cycle,
Height: log.Height,
R: log.R,
P: log.P,
M: log.M,
Time: log.Time,
}
err = VrfRPTable.Add(vrfRP)
if err != nil {
return nil, err
}
kvs, err = VrfRPTable.Save()
if err != nil {
return nil, err
}
}
return kvs, nil
}
func (d *DPos) execLocal(receipt *types.ReceiptData) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
if receipt.GetTy() != types.ExecOk {
return dbSet, nil
}
for _, item := range receipt.Logs {
if item.Ty >= dty.CandidatorStatusRegist && item.Ty <= dty.CandidatorStatusCancelRegist {
var candLog dty.ReceiptCandicator
err := types.Decode(item.Log, &candLog)
if err != nil {
return nil, err
}
kvs, err := d.updateCandVote(&candLog)
if err != nil {
return nil, err
}
dbSet.KV = append(dbSet.KV, kvs...)
} else if item.Ty >= dty.VrfStatusMRegist && item.Ty <= dty.VrfStatusRPRegist {
var vrfLog dty.ReceiptVrf
err := types.Decode(item.Log, &vrfLog)
if err != nil {
return nil, err
}
kvs, err := d.updateVrf(&vrfLog)
if err != nil {
return nil, err
}
dbSet.KV = append(dbSet.KV, kvs...)
}
}
return dbSet, nil
}
//ExecLocal_Regist method
func (d *DPos) ExecLocal_Regist(payload *dty.DposCandidatorRegist, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return d.execLocal(receiptData)
}
//ExecLocal_CancelRegist method
func (d *DPos) ExecLocal_CancelRegist(payload *dty.DposCandidatorCancelRegist, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return d.execLocal(receiptData)
}
//ExecLocal_ReRegist method
func (d *DPos) ExecLocal_ReRegist(payload *dty.DposCandidatorRegist, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return d.execLocal(receiptData)
}
//ExecLocal_Vote method
func (d *DPos) ExecLocal_Vote(payload *dty.DposVote, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return d.execLocal(receiptData)
}
//ExecLocal_CancelVote method
func (d *DPos) ExecLocal_CancelVote(payload *dty.DposCancelVote, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return d.execLocal(receiptData)
}
//ExecLocal_VrfMRegist method
func (d *DPos) ExecLocal_VrfMRegist(payload *dty.DposVrfMRegist, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return d.execLocal(receiptData)
}
//ExecLocal_VrfRPRegist method
func (d *DPos) ExecLocal_VrfRPRegist(payload *dty.DposVrfRPRegist, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return d.execLocal(receiptData)
}
\ 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 executor
import (
"github.com/33cn/chain33/types"
dty "github.com/33cn/plugin/plugin/dapp/dposvote/types"
)
//Query_QueryCandidatorByPubkeys method
func (d *DPos) Query_QueryCandidatorByPubkeys(in *dty.CandidatorQuery) (types.Message, error) {
return queryCands(d.GetLocalDB(), in)
}
//Query_QueryCandidatorByTopN method
func (d *DPos) Query_QueryCandidatorByTopN(in *dty.CandidatorQuery) (types.Message, error) {
return queryTopNCands(d.GetLocalDB(), in)
}
//Query_QueryVote method
func (d *DPos) Query_QueryVote(in *dty.DposVoteQuery) (types.Message, error) {
return queryVote(d.GetLocalDB(), in)
}
//Query_QueryVrfByTime method
func (d *DPos) Query_QueryVrfByTime(in *dty.DposVrfQuery) (types.Message, error) {
return queryVrfByTime(d.GetLocalDB(), in)
}
//Query_QueryVrfByCycle method
func (d *DPos) Query_QueryVrfByCycle(in *dty.DposVrfQuery) (types.Message, error) {
return queryVrfByCycle(d.GetLocalDB(), in)
}
// 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 dposvote
import (
"github.com/33cn/chain33/pluginmgr"
"github.com/33cn/plugin/plugin/dapp/dposvote/commands"
"github.com/33cn/plugin/plugin/dapp/dposvote/executor"
"github.com/33cn/plugin/plugin/dapp/dposvote/types"
)
func init() {
pluginmgr.Register(&pluginmgr.PluginBase{
Name: types.DPosX,
ExecName: executor.GetName(),
Exec: executor.Init,
Cmd: commands.DPosCmd,
})
}
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;
//CandidatorInfo 候选节点信息
message CandidatorInfo {
bytes pubkey = 1; //候选节点的公钥
string address = 2; //后续节点的地址
string ip = 3; //候选节点的运行IP
int64 votes = 4; //候选节点的投票数
int64 status = 5; //候选节点的状态,0:注册,1:当选,2:取消注册
int64 preStatus = 6;
int64 startTime = 7; //创建候选者的时间
int64 startHeight = 8; //创建候选者的时间
string startTxHash = 9; //创建候选者的交易hash
int64 startIndex = 10; //创建候选者的交易index
int64 index = 11;
int64 preIndex = 12;
repeated DposVoter voters = 13;
}
message DposVoter{
string fromAddr = 1;
bytes pubkey = 2; //候选节点的公钥
int64 votes = 3; //投给候选节点的票数,不能超过锁在合约中的未使用票数
int64 index = 4;
int64 time = 5;
}
//Candidator 候选节点信息
message Candidator {
bytes pubkey = 1; //候选节点的公钥
string address = 2; //后续节点的地址
string ip = 3; //候选节点的运行IP
int64 votes = 4; //候选节点的投票数
int64 status = 5; //候选节点的状态,0:注册,1:当选,2:取消注册
}
//DposCandidatorRegist 注册Dpos候选节点,必须抵押一定数量的币,比如:10000个币
message DposCandidatorRegist{
string pubkey = 1; //候选节点的公钥
string address = 2; //候选节点的地址
string ip = 3; //候选节点的共识IP地址
}
//DposCandidatorCancelRegist 注销Dpos候选节点,解冻抵押的币
message DposCandidatorCancelRegist{
string pubkey = 1; //候选节点的公钥
string address = 2; //候选节点的地址
}
//DposVote 为Dpos候选节点投票
message DposVote{
string fromAddr = 1;
string pubkey = 2; //候选节点的公钥
int64 votes = 3; //投给候选节点的票数,不能超过锁在合约中的未使用票数
}
//DposCancelVote 撤销为Dpos候选节点投票
message DposCancelVote{
string pubkey = 1; //候选节点的公钥
int64 votes = 2; //撤销投给候选节点的票数,不超过之前投给该候选节点的总票数,投票3天之后才可以撤销投票
}
//DposVoteAction DposVote动作
message DposVoteAction {
oneof value {
DposCandidatorRegist regist = 1;
DposCandidatorCancelRegist cancelRegist = 2;
DposCandidatorRegist reRegist = 3;
DposVote vote = 4;
DposCancelVote cancelVote = 5;
CandidatorQuery candidatorQuery = 6;
DposVoteQuery voteQuery = 7;
DposVrfMRegist registVrfM = 8;
DposVrfRPRegist registVrfRP = 9;
DposVrfQuery vrfQuery = 10;
}
int32 ty = 11;
}
message CandidatorQuery{
repeated string pubkeys = 1; //候选节点公钥集合
int32 topN = 2; //topN
int32 ty = 3; //1:按公钥集合查询,2:按topN票数查询
}
message CandidatorReply{
repeated Candidator candidators = 1; //候选节点
}
message DposVoteQuery{
repeated string pubkeys = 1; //候选节点的公钥,如果为空,则查询所有,否则,查询该地址给具体候选节点的投票
string addr = 2; //要查询的地址
}
message DposVoteReply{
repeated DposVoter votes = 1; //某地址对具体候选节点的投票情况
}
//ReceiptCandicator 候选者收据信息
message ReceiptCandicator {
int64 Index = 1;
bytes pubkey = 2;
string address = 3;
int64 status = 4;
int64 preStatus = 5;
bool statusChange = 6;
bool voted = 7;
int64 votes = 8;
string fromAddr = 9;
CandidatorInfo candInfo = 10;
int64 time = 11;
}
message DposVrfM{
int64 Index = 1;
bytes pubkey = 2;
int64 cycle = 3;
int64 height = 4;
bytes m = 5; //vrf的输入
int64 time = 6;
}
message DposVrfRP{
int64 Index = 1;
bytes pubkey = 2;
int64 cycle = 3;
int64 height = 4;
bytes m = 5; //vrf的输入
bytes r = 6; //vrf的hash
bytes p = 7; //vrf的hash的proof
int64 time = 8;
}
message DposVrfMRegist{
string pubkey = 1;
int64 cycle = 2;
string m = 3; //vrf的输入
}
message DposVrfRPRegist{
string pubkey = 1;
int64 cycle = 2;
string r = 3; //vrf的hash
string p = 4; //vrf的hash的proof
}
//ReceiptVrf vrf收据信息
message ReceiptVrf {
int64 Index = 1;
bytes pubkey = 2;
int64 status = 3;
int64 cycle = 4;
int64 height = 5;
bytes m = 6;
bytes r = 7;
bytes p = 8;
int64 time = 9;
}
message VrfInfo {
int64 Index = 1;
bytes pubkey = 2;
int64 cycle = 4;
int64 height = 5;
bytes m = 6;
bytes r = 7;
bytes p = 8;
int64 time = 9;
}
message DposVrfQuery{
int64 ty = 1;
int64 timestamp = 2;
int64 cycle = 3;
}
message DposVrfReply{
repeated VrfInfo vrf = 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"
"testing"
commonlog "github.com/33cn/chain33/common/log"
"github.com/33cn/chain33/rpc/jsonclient"
rpctypes "github.com/33cn/chain33/rpc/types"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/util/testnode"
pty "github.com/33cn/plugin/plugin/dapp/guess/types"
"github.com/stretchr/testify/assert"
_ "github.com/33cn/chain33/system"
_ "github.com/33cn/plugin/plugin"
)
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: testStartRawTxCmd},
{fn: testBetRawTxCmd},
{fn: testStopBetRawTxCmd},
{fn: testPublishRawTxCmd},
{fn: testAbortRawTxCmd},
}
for _, testCase := range testCases {
err := testCase.fn(t, jrpcClient)
assert.Nil(t, err)
}
testCases = []struct {
fn func(*testing.T, *jsonclient.JSONClient) error
}{
{fn: testQueryGameByID},
{fn: testQueryGamesByAddr},
{fn: testQueryGamesByStatus},
{fn: testQueryGamesByAdminAddr},
{fn: testQueryGamesByAddrStatus},
{fn: testQueryGamesByAdminStatus},
{fn: testQueryGamesByCategoryStatus},
}
for index, testCase := range testCases {
err := testCase.fn(t, jrpcClient)
assert.Equal(t, err, types.ErrNotFound, fmt.Sprint(index))
}
testCases = []struct {
fn func(*testing.T, *jsonclient.JSONClient) error
}{
{fn: testQueryGamesByIDs},
}
for index, testCase := range testCases {
err := testCase.fn(t, jrpcClient)
assert.Equal(t, err, nil, fmt.Sprint(index))
}
}
func testStartRawTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
payload := &pty.GuessGameStart{Topic: "WorldCup Final", Options: "A:France;B:Claodia", Category: "football", MaxBetsOneTime: 100e8, MaxBetsNumber: 1000e8, DevFeeFactor: 5, DevFeeAddr: "1D6RFZNp2rh6QdbcZ1d7RWuBUz61We6SD7", PlatFeeFactor: 5, PlatFeeAddr: "1PHtChNt3UcfssR7v7trKSk3WJtAWjKjjX"}
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(pty.GuessX),
ActionName: pty.CreateStartTx,
Payload: types.MustPBToJSON(payload),
}
var res string
return jrpc.Call("Chain33.CreateTransaction", params, &res)
}
func testBetRawTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
payload := &pty.GuessGameBet{GameID: "0x76dae82fcbe554d4b8df5ed1460d71dcac86a50864649a0df43e0c50b245f004", Option: "A", BetsNum: 5e8}
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(pty.GuessX),
ActionName: pty.CreateBetTx,
Payload: types.MustPBToJSON(payload),
}
var res string
return jrpc.Call("Chain33.CreateTransaction", params, &res)
}
func testStopBetRawTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
payload := &pty.GuessGameStopBet{GameID: "0x76dae82fcbe554d4b8df5ed1460d71dcac86a50864649a0df43e0c50b245f004"}
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(pty.GuessX),
ActionName: pty.CreateStopBetTx,
Payload: types.MustPBToJSON(payload),
}
var res string
return jrpc.Call("Chain33.CreateTransaction", params, &res)
}
func testPublishRawTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
payload := &pty.GuessGamePublish{GameID: "0x76dae82fcbe554d4b8df5ed1460d71dcac86a50864649a0df43e0c50b245f004", Result: "A"}
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(pty.GuessX),
ActionName: pty.CreatePublishTx,
Payload: types.MustPBToJSON(payload),
}
var res string
return jrpc.Call("Chain33.CreateTransaction", params, &res)
}
func testAbortRawTxCmd(t *testing.T, jrpc *jsonclient.JSONClient) error {
payload := &pty.GuessGameAbort{GameID: "0x76dae82fcbe554d4b8df5ed1460d71dcac86a50864649a0df43e0c50b245f004"}
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(pty.GuessX),
ActionName: pty.CreateAbortTx,
Payload: types.MustPBToJSON(payload),
}
var res string
return jrpc.Call("Chain33.CreateTransaction", params, &res)
}
func testQueryGameByID(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{}
var params rpctypes.Query4Jrpc
req := &pty.QueryGuessGameInfo{}
params.Execer = pty.GuessX
params.FuncName = pty.FuncNameQueryGameByID
params.Payload = types.MustPBToJSON(req)
rep = &pty.ReplyGuessGameInfo{}
return jrpc.Call("Chain33.Query", params, rep)
}
func testQueryGamesByAddr(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{}
var params rpctypes.Query4Jrpc
req := &pty.QueryGuessGameInfo{}
params.Execer = pty.GuessX
params.FuncName = pty.FuncNameQueryGameByAddr
params.Payload = types.MustPBToJSON(req)
rep = &pty.GuessGameRecords{}
return jrpc.Call("Chain33.Query", params, rep)
}
func testQueryGamesByIDs(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{}
var params rpctypes.Query4Jrpc
req := &pty.QueryGuessGameInfos{}
params.Execer = pty.GuessX
params.FuncName = pty.FuncNameQueryGamesByIDs
params.Payload = types.MustPBToJSON(req)
rep = &pty.ReplyGuessGameInfos{}
return jrpc.Call("Chain33.Query", params, rep)
}
func testQueryGamesByStatus(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{}
var params rpctypes.Query4Jrpc
req := &pty.QueryGuessGameInfo{}
params.Execer = pty.GuessX
params.FuncName = pty.FuncNameQueryGameByStatus
params.Payload = types.MustPBToJSON(req)
rep = &pty.GuessGameRecords{}
return jrpc.Call("Chain33.Query", params, rep)
}
func testQueryGamesByAdminAddr(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{}
var params rpctypes.Query4Jrpc
req := &pty.QueryGuessGameInfo{}
params.Execer = pty.GuessX
params.FuncName = pty.FuncNameQueryGameByAdminAddr
params.Payload = types.MustPBToJSON(req)
rep = &pty.GuessGameRecords{}
return jrpc.Call("Chain33.Query", params, rep)
}
func testQueryGamesByAddrStatus(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{}
var params rpctypes.Query4Jrpc
req := &pty.QueryGuessGameInfo{}
params.Execer = pty.GuessX
params.FuncName = pty.FuncNameQueryGameByAddrStatus
params.Payload = types.MustPBToJSON(req)
rep = &pty.GuessGameRecords{}
return jrpc.Call("Chain33.Query", params, rep)
}
func testQueryGamesByAdminStatus(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{}
var params rpctypes.Query4Jrpc
req := &pty.QueryGuessGameInfo{}
params.Execer = pty.GuessX
params.FuncName = pty.FuncNameQueryGameByAdminStatus
params.Payload = types.MustPBToJSON(req)
rep = &pty.GuessGameRecords{}
return jrpc.Call("Chain33.Query", params, rep)
}
func testQueryGamesByCategoryStatus(t *testing.T, jrpc *jsonclient.JSONClient) error {
var rep interface{}
var params rpctypes.Query4Jrpc
req := &pty.QueryGuessGameInfo{}
params.Execer = pty.GuessX
params.FuncName = pty.FuncNameQueryGameByCategoryStatus
params.Payload = types.MustPBToJSON(req)
rep = &pty.GuessGameRecords{}
return jrpc.Call("Chain33.Query", params, rep)
}
// 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
//dpos action ty
const (
DposVoteActionRegist = iota + 1
DposVoteActionCancelRegist
DposVoteActionReRegist
DposVoteActionVote
DposVoteActionCancelVote
DposVoteActionRegistVrfM
DposVoteActionRegistVrfRP
CandidatorStatusRegist = iota + 1
CandidatorStatusVoted
CandidatorStatusCancelVoted
CandidatorStatusCancelRegist
VrfStatusMRegist = iota + 1
VrfStatusRPRegist
)
//log ty
const (
TyLogCandicatorRegist = 1001
TyLogCandicatorVoted = 1002
TyLogCandicatorCancelRegist = 1003
TyLogCandicatorReRegist = 1004
TyLogVrfMRegist = 1005
TyLogVrfRPRegist = 1006
)
const (
VoteFrozenTime = 3 * 24 * 3600
RegistFrozenCoins = 1000000000000
)
//包的名字可以通过配置文件来配置
//建议用github的组织名称,或者用户名字开头, 再加上自己的插件的名字
//如果发生重名,可以通过配置文件修改这些名字
var (
DPosX = "dpos"
ExecerDposVote = []byte(DPosX)
)
const (
//FuncNameQueryCandidatorByPubkeys func name
FuncNameQueryCandidatorByPubkeys = "QueryCandidatorByPubkeys"
//FuncNameQueryCandidatorByTopN func name
FuncNameQueryCandidatorByTopN = "QueryCandidatorByTopN"
//FuncNameQueryVrfByTime func name
FuncNameQueryVrfByTime = "QueryVrfByTime"
//FuncNameQueryVrfByCycle func name
FuncNameQueryVrfByCycle = "QueryVrfByCycle"
//FuncNameQueryVote func name
FuncNameQueryVote = "QueryVote"
//CreateRegistTx 创建注册候选节点交易
CreateRegistTx = "Regist"
//CreateCancelRegistTx 创建取消候选节点的交易
CreateCancelRegistTx = "CancelRegist"
//CreateReRegistTx 创建重新注册候选节点的交易
CreateReRegistTx = "ReRegist"
//CreateVoteTx 创建为候选节点投票的交易
CreateVoteTx = "Vote"
//CreateCancelVoteTx 创建取消对候选节点投票的交易
CreateCancelVoteTx = "CancelVote"
//CreateRegistVrfMTx 创建注册Vrf的M信息的交易
CreateRegistVrfMTx = "RegistVrfM"
//CreateRegistVrfRPTx 创建注册Vrf的R/P信息的交易
CreateRegistVrfRPTx = "RegistVrfRP"
//QueryVrfByTime 创建根据time查询Vrf信息查询
QueryVrfByTime = 1
//QueryVrfByCycle 创建根据cycle查询Vrf信息查询
QueryVrfByCycle = 2
)
// 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"
// Errors for Dpos
var (
ErrNotEnoughVotes = errors.New("ErrNotEnoughVotes")
ErrCandidatorExist = errors.New("ErrCandidatorExist")
ErrCandidatorInvalidStatus = errors.New("ErrCandidatorInvalidStatus")
ErrCandidatorNotExist = errors.New("ErrCandidatorNotExist")
ErrCandidatorNotEnough = errors.New("ErrCandidatorNotEnough")
ErrCandidatorNotLegal = errors.New("ErrCandidatorNotLegal")
ErrVrfMNotRegisted = errors.New("ErrVrfMNotRegisted")
ErrVrfMAlreadyRegisted = errors.New("ErrVrfMAlreadyRegisted")
ErrVrfRPAlreadyRegisted = errors.New("ErrVrfRPAlreadyRegisted")
ErrNoPrivilege = errors.New("ErrNoPrivilege")
ErrParamStatusInvalid = errors.New("ErrParamStatusInvalid")
ErrParamAddressMustnotEmpty = errors.New("ErrParamAddressMustnotEmpty")
ErrSaveTable = errors.New("ErrSaveTable")
)
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: voter
index: FromAddr,Pubkey,Votes,Index,Time
*/
var opt_dpos_voter = &table.Option{
Prefix: "LODB-dpos",
Name: "voter",
Primary: "index",
Index: []string{"addr", "pubkey"},
}
//NewDposVoteTable 新建表
func NewDposVoteTable(kvdb db.KV) *table.Table {
rowmeta := NewDposVoterRow()
table, err := table.NewTable(rowmeta, kvdb, opt_dpos_voter)
if err != nil {
panic(err)
}
return table
}
//DposVoterRow table meta 结构
type DposVoterRow struct {
*DposVoter
}
//NewDposVoterRow 新建一个meta 结构
func NewDposVoterRow() *DposVoterRow {
return &DposVoterRow{DposVoter: &DposVoter{}}
}
//CreateRow 新建数据行
func (tx *DposVoterRow) CreateRow() *table.Row {
return &table.Row{Data: &DposVoter{}}
}
//SetPayload 设置数据
func (tx *DposVoterRow) SetPayload(data types.Message) error {
if txdata, ok := data.(*DposVoter); ok {
tx.DposVoter = txdata
return nil
}
return types.ErrTypeAsset
}
//Get 按照indexName 查询 indexValue
func (tx *DposVoterRow) Get(key string) ([]byte, error) {
if key == "index" {
return []byte(fmt.Sprintf("%018d", tx.Index)), nil
} else if key == "addr" {
return []byte(tx.FromAddr), nil
} else if key == "pubkey" {
return tx.Pubkey, nil
}
return nil, types.ErrNotFound
}
var opt_dpos_candidator = &table.Option{
Prefix: "LODB-dpos",
Name: "candidator",
Primary: "pubkey",
Index: []string{"status"},
}
//NewDposCandidatorTable 新建表
func NewDposCandidatorTable(kvdb db.KV) *table.Table {
rowmeta := NewDposCandidatorRow()
table, err := table.NewTable(rowmeta, kvdb, opt_dpos_candidator)
if err != nil {
panic(err)
}
return table
}
//DposCandidatorRow table meta 结构
type DposCandidatorRow struct {
*CandidatorInfo
}
//NewDposCandidatorRow 新建一个meta 结构
func NewDposCandidatorRow() *DposCandidatorRow {
return &DposCandidatorRow{CandidatorInfo: &CandidatorInfo{}}
}
//CreateRow 新建数据行
func (tx *DposCandidatorRow) CreateRow() *table.Row {
return &table.Row{Data: &CandidatorInfo{}}
}
//SetPayload 设置数据
func (tx *DposCandidatorRow) SetPayload(data types.Message) error {
if txdata, ok := data.(*CandidatorInfo); ok {
tx.CandidatorInfo = txdata
return nil
}
return types.ErrTypeAsset
}
//Get 按照indexName 查询 indexValue
func (tx *DposCandidatorRow) Get(key string) ([]byte, error) {
if key == "pubkey" {
return tx.Pubkey, nil
} else if key == "status" {
return []byte(fmt.Sprintf("%2d", tx.Status)), nil
}
return nil, types.ErrNotFound
}
var opt_dpos_vrfm = &table.Option{
Prefix: "LODB-dpos",
Name: "vrfm",
Primary: "index",
Index: []string{"pubkey_cycle"},
}
//NewDposVrfMTable 新建表
func NewDposVrfMTable(kvdb db.KV) *table.Table {
rowmeta := NewDposVrfMRow()
table, err := table.NewTable(rowmeta, kvdb, opt_dpos_vrfm)
if err != nil {
panic(err)
}
return table
}
//DposVrfMRow table meta 结构
type DposVrfMRow struct {
*DposVrfM
}
//NewDposVrfMRow 新建一个meta 结构
func NewDposVrfMRow() *DposVrfMRow {
return &DposVrfMRow{DposVrfM: &DposVrfM{}}
}
//CreateRow 新建数据行
func (tx *DposVrfMRow) CreateRow() *table.Row {
return &table.Row{Data: &DposVrfM{}}
}
//SetPayload 设置数据
func (tx *DposVrfMRow) SetPayload(data types.Message) error {
if txdata, ok := data.(*DposVrfM); ok {
tx.DposVrfM = txdata
return nil
}
return types.ErrTypeAsset
}
//Get 按照indexName 查询 indexValue
func (tx *DposVrfMRow) Get(key string) ([]byte, error) {
if key == "index" {
return []byte(fmt.Sprintf("%018d", tx.Index)), nil
} else if key == "pubkey_cycle" {
return []byte(fmt.Sprintf("%X:%018d", tx.Pubkey, tx.Cycle)), nil
}
return nil, types.ErrNotFound
}
var opt_dpos_vrfrp = &table.Option{
Prefix: "LODB-dpos",
Name: "vrfrp",
Primary: "index",
Index: []string{"pubkey_cycle"},
}
//NewDposVrfRPTable 新建表
func NewDposVrfRPTable(kvdb db.KV) *table.Table {
rowmeta := NewDposVrfRPRow()
table, err := table.NewTable(rowmeta, kvdb, opt_dpos_vrfrp)
if err != nil {
panic(err)
}
return table
}
//DposVrfRPRow table meta 结构
type DposVrfRPRow struct {
*DposVrfRP
}
//NewDposVrfRPRow 新建一个meta 结构
func NewDposVrfRPRow() *DposVrfRPRow {
return &DposVrfRPRow{DposVrfRP: &DposVrfRP{}}
}
//CreateRow 新建数据行
func (tx *DposVrfRPRow) CreateRow() *table.Row {
return &table.Row{Data: &DposVrfRP{}}
}
//SetPayload 设置数据
func (tx *DposVrfRPRow) SetPayload(data types.Message) error {
if txdata, ok := data.(*DposVrfRP); ok {
tx.DposVrfRP = txdata
return nil
}
return types.ErrTypeAsset
}
//Get 按照indexName 查询 indexValue
func (tx *DposVrfRPRow) Get(key string) ([]byte, error) {
if key == "index" {
return []byte(fmt.Sprintf("%018d", tx.Index)), nil
} else if key == "pubkey_cycle" {
return []byte(fmt.Sprintf("%X:%018d", tx.Pubkey, tx.Cycle)), 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.RegistorExecutor(DPosX, NewType())
types.AllowUserExec = append(types.AllowUserExec, ExecerDposVote)
types.RegisterDappFork(DPosX, "Enable", 0)
}
// GuessType struct
type DPosType struct {
types.ExecTypeBase
}
// NewType method
func NewType() *DPosType {
c := &DPosType{}
c.SetChild(c)
return c
}
// GetPayload method
func (t *DPosType) GetPayload() types.Message {
return &DposVoteAction{}
}
// GetTypeMap method
func (t *DPosType) GetTypeMap() map[string]int32 {
return map[string]int32{
"Regist": DposVoteActionRegist,
"CancelRegist": DposVoteActionCancelRegist,
"ReRegist": DposVoteActionReRegist,
"Vote": DposVoteActionVote,
"CancelVote": DposVoteActionCancelVote,
"RegistVrfM": DposVoteActionRegistVrfM,
"RegistVrfRP": DposVoteActionRegistVrfRP,
}
}
// GetLogMap method
func (t *DPosType) GetLogMap() map[int64]*types.LogInfo {
return map[int64]*types.LogInfo{
TyLogCandicatorRegist: {Ty: reflect.TypeOf(ReceiptCandicator{}), Name: "TyLogCandicatorRegist"},
TyLogCandicatorVoted: {Ty: reflect.TypeOf(ReceiptCandicator{}), Name: "TyLogCandicatorVoted"},
TyLogCandicatorCancelRegist: {Ty: reflect.TypeOf(ReceiptCandicator{}), Name: "TyLogCandicatorCancelRegist"},
TyLogVrfMRegist: {Ty: reflect.TypeOf(ReceiptVrf{}), Name: "TyLogVrfMRegist"},
TyLogVrfRPRegist: {Ty: reflect.TypeOf(ReceiptVrf{}), Name: "TyLogVrfRPRegist"},
}
}
This diff is collapsed.
...@@ -3,6 +3,7 @@ package init ...@@ -3,6 +3,7 @@ package init
import ( import (
_ "github.com/33cn/plugin/plugin/dapp/blackwhite" //auto gen _ "github.com/33cn/plugin/plugin/dapp/blackwhite" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/cert" //auto gen _ "github.com/33cn/plugin/plugin/dapp/cert" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/dposvote" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/echo" //auto gen _ "github.com/33cn/plugin/plugin/dapp/echo" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/evm" //auto gen _ "github.com/33cn/plugin/plugin/dapp/evm" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/game" //auto gen _ "github.com/33cn/plugin/plugin/dapp/game" //auto gen
......
...@@ -339,6 +339,16 @@ func testProcCreateNewAccount(t *testing.T, wallet *Wallet) { ...@@ -339,6 +339,16 @@ func testProcCreateNewAccount(t *testing.T, wallet *Wallet) {
} }
println("TestProcCreateNewAccount end") println("TestProcCreateNewAccount end")
println("--------------------------") println("--------------------------")
Privkey1 := "85CA38F5FB65E5E13403F0704CA6DC479D8D18FFA5D87CE5A966838C9694EAFE"
privkeybyte1, _ := common.FromHex(Privkey1)
priv1, _ := cr.PrivKeyFromBytes(privkeybyte1)
fmt.Printf("pubkey:%X\n", priv1.PubKey().Bytes())
fmt.Printf("pubkey:%s\n", priv1.PubKey().KeyString())
fmt.Printf("priv:%X\n", priv1.Bytes())
addr = address.PubKeyToAddress(priv1.PubKey().Bytes())
fmt.Printf("address:%s\n", addr.String())
fmt.Printf("addr:%X\n", addr.Hash160)
} }
func equal(acc1 types.Account, acc2 types.Account) bool { func equal(acc1 types.Account, acc2 types.Account) bool {
......
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