Implement basic version of dispute manager, slightly refactor consensus package
This commit is contained in:
parent
56c23a9087
commit
35e7994da7
@ -32,7 +32,7 @@ func (cp *CommitPool) IsExistingCommit(commitMsg *types2.Message) bool {
|
|||||||
|
|
||||||
consensusMessage := commitMsg.Payload
|
consensusMessage := commitMsg.Payload
|
||||||
var exists bool
|
var exists bool
|
||||||
for _, v := range cp.commitMsgs[consensusMessage.ConsensusID] {
|
for _, v := range cp.commitMsgs[consensusMessage.Task.ConsensusID] {
|
||||||
if v.From == commitMsg.From {
|
if v.From == commitMsg.From {
|
||||||
exists = true
|
exists = true
|
||||||
}
|
}
|
||||||
@ -54,7 +54,7 @@ func (cp *CommitPool) AddCommit(commit *types2.Message) {
|
|||||||
cp.mut.Lock()
|
cp.mut.Lock()
|
||||||
defer cp.mut.Unlock()
|
defer cp.mut.Unlock()
|
||||||
|
|
||||||
consensusID := commit.Payload.ConsensusID
|
consensusID := commit.Payload.Task.ConsensusID
|
||||||
if _, ok := cp.commitMsgs[consensusID]; !ok {
|
if _, ok := cp.commitMsgs[consensusID]; !ok {
|
||||||
cp.commitMsgs[consensusID] = []*types2.Message{}
|
cp.commitMsgs[consensusID] = []*types2.Message{}
|
||||||
}
|
}
|
||||||
|
@ -26,15 +26,17 @@ type PBFTConsensusManager struct {
|
|||||||
prePreparePool *PrePreparePool
|
prePreparePool *PrePreparePool
|
||||||
preparePool *PreparePool
|
preparePool *PreparePool
|
||||||
commitPool *CommitPool
|
commitPool *CommitPool
|
||||||
consensusInfo map[string]*ConsensusData
|
consensusMap map[string]*Consensus
|
||||||
ethereumClient *ethclient.EthereumClient
|
ethereumClient *ethclient.EthereumClient
|
||||||
miner *Miner
|
miner *Miner
|
||||||
eventCache cache.EventCache
|
eventCache cache.EventCache
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConsensusData struct {
|
type Consensus struct {
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
alreadySubmitted bool
|
Finished bool
|
||||||
|
IsCurrentMinerLeader bool
|
||||||
|
Task *types2.DioneTask
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPBFTConsensusManager(psb *pubsub.PubSubRouter, minApprovals int, privKey []byte, ethereumClient *ethclient.EthereumClient, miner *Miner, evc cache.EventCache) *PBFTConsensusManager {
|
func NewPBFTConsensusManager(psb *pubsub.PubSubRouter, minApprovals int, privKey []byte, ethereumClient *ethclient.EthereumClient, miner *Miner, evc cache.EventCache) *PBFTConsensusManager {
|
||||||
@ -48,7 +50,7 @@ func NewPBFTConsensusManager(psb *pubsub.PubSubRouter, minApprovals int, privKey
|
|||||||
pcm.privKey = privKey
|
pcm.privKey = privKey
|
||||||
pcm.ethereumClient = ethereumClient
|
pcm.ethereumClient = ethereumClient
|
||||||
pcm.eventCache = evc
|
pcm.eventCache = evc
|
||||||
pcm.consensusInfo = map[string]*ConsensusData{}
|
pcm.consensusMap = map[string]*Consensus{}
|
||||||
pcm.psb.Hook(types.MessageTypePrePrepare, pcm.handlePrePrepare)
|
pcm.psb.Hook(types.MessageTypePrePrepare, pcm.handlePrePrepare)
|
||||||
pcm.psb.Hook(types.MessageTypePrepare, pcm.handlePrepare)
|
pcm.psb.Hook(types.MessageTypePrepare, pcm.handlePrepare)
|
||||||
pcm.psb.Hook(types.MessageTypeCommit, pcm.handleCommit)
|
pcm.psb.Hook(types.MessageTypeCommit, pcm.handleCommit)
|
||||||
@ -56,11 +58,10 @@ func NewPBFTConsensusManager(psb *pubsub.PubSubRouter, minApprovals int, privKey
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (pcm *PBFTConsensusManager) Propose(consensusID string, task types2.DioneTask, requestEvent *dioneOracle.DioneOracleNewOracleRequest) error {
|
func (pcm *PBFTConsensusManager) Propose(consensusID string, task types2.DioneTask, requestEvent *dioneOracle.DioneOracleNewOracleRequest) error {
|
||||||
pcm.consensusInfo[consensusID] = &ConsensusData{}
|
pcm.createConsensusInfo(&task, true)
|
||||||
|
|
||||||
prePrepareMsg, err := pcm.prePreparePool.CreatePrePrepare(
|
prePrepareMsg, err := pcm.prePreparePool.CreatePrePrepare(
|
||||||
consensusID,
|
&task,
|
||||||
task,
|
|
||||||
requestEvent.ReqID.String(),
|
requestEvent.ReqID.String(),
|
||||||
requestEvent.CallbackAddress.Bytes(),
|
requestEvent.CallbackAddress.Bytes(),
|
||||||
requestEvent.CallbackMethodID[:],
|
requestEvent.CallbackMethodID[:],
|
||||||
@ -74,6 +75,9 @@ func (pcm *PBFTConsensusManager) Propose(consensusID string, task types2.DioneTa
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (pcm *PBFTConsensusManager) handlePrePrepare(message *types.Message) {
|
func (pcm *PBFTConsensusManager) handlePrePrepare(message *types.Message) {
|
||||||
|
if message.Payload.Task.Miner == pcm.miner.address {
|
||||||
|
return
|
||||||
|
}
|
||||||
if pcm.prePreparePool.IsExistingPrePrepare(message) {
|
if pcm.prePreparePool.IsExistingPrePrepare(message) {
|
||||||
logrus.Debug("received existing pre_prepare msg, dropping...")
|
logrus.Debug("received existing pre_prepare msg, dropping...")
|
||||||
return
|
return
|
||||||
@ -94,6 +98,9 @@ func (pcm *PBFTConsensusManager) handlePrePrepare(message *types.Message) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("failed to create prepare message: %w", err)
|
logrus.Errorf("failed to create prepare message: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pcm.createConsensusInfo(&message.Payload.Task, false)
|
||||||
|
|
||||||
pcm.psb.BroadcastToServiceTopic(prepareMsg)
|
pcm.psb.BroadcastToServiceTopic(prepareMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +121,7 @@ func (pcm *PBFTConsensusManager) handlePrepare(message *types.Message) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if pcm.preparePool.PreparePoolSize(message.Payload.ConsensusID) >= pcm.minApprovals {
|
if pcm.preparePool.PreparePoolSize(message.Payload.Task.ConsensusID) >= pcm.minApprovals {
|
||||||
commitMsg, err := pcm.commitPool.CreateCommit(message, pcm.privKey)
|
commitMsg, err := pcm.commitPool.CreateCommit(message, pcm.privKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("failed to create commit message: %w", err)
|
logrus.Errorf("failed to create commit message: %w", err)
|
||||||
@ -141,21 +148,22 @@ func (pcm *PBFTConsensusManager) handleCommit(message *types.Message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
consensusMsg := message.Payload
|
consensusMsg := message.Payload
|
||||||
if pcm.commitPool.CommitSize(consensusMsg.ConsensusID) >= pcm.minApprovals {
|
if pcm.commitPool.CommitSize(consensusMsg.Task.ConsensusID) >= pcm.minApprovals {
|
||||||
if info, ok := pcm.consensusInfo[consensusMsg.ConsensusID]; ok {
|
info := pcm.consensusMap[consensusMsg.Task.ConsensusID]
|
||||||
info.mutex.Lock()
|
info.mutex.Lock()
|
||||||
defer info.mutex.Unlock()
|
defer info.mutex.Unlock()
|
||||||
if info.alreadySubmitted {
|
if info.Finished {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logrus.Infof("Submitting on-chain result for consensus ID: %s", consensusMsg.ConsensusID)
|
if info.IsCurrentMinerLeader {
|
||||||
reqID, ok := new(big.Int).SetString(consensusMsg.RequestID, 10)
|
logrus.Infof("Submitting on-chain result for consensus ID: %s", consensusMsg.Task.ConsensusID)
|
||||||
|
reqID, ok := new(big.Int).SetString(consensusMsg.Task.RequestID, 10)
|
||||||
if !ok {
|
if !ok {
|
||||||
logrus.Errorf("Failed to parse request ID: %v", consensusMsg.RequestID)
|
logrus.Errorf("Failed to parse request ID: %v", consensusMsg.Task.RequestID)
|
||||||
}
|
}
|
||||||
callbackAddress := common.BytesToAddress(consensusMsg.CallbackAddress)
|
callbackAddress := common.BytesToAddress(consensusMsg.Task.CallbackAddress)
|
||||||
|
|
||||||
request, err := pcm.eventCache.GetOracleRequestEvent("request_" + consensusMsg.RequestID)
|
request, err := pcm.eventCache.GetOracleRequestEvent("request_" + consensusMsg.Task.RequestID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Failed to get request from cache: %v", err.Error())
|
logrus.Errorf("Failed to get request from cache: %v", err.Error())
|
||||||
return
|
return
|
||||||
@ -165,7 +173,25 @@ func (pcm *PBFTConsensusManager) handleCommit(message *types.Message) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Failed to submit on-chain result: %v", err)
|
logrus.Errorf("Failed to submit on-chain result: %v", err)
|
||||||
}
|
}
|
||||||
info.alreadySubmitted = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info.Finished = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pcm *PBFTConsensusManager) createConsensusInfo(task *types2.DioneTask, isLeader bool) {
|
||||||
|
pcm.consensusMap[task.ConsensusID] = &Consensus{
|
||||||
|
IsCurrentMinerLeader: isLeader,
|
||||||
|
Task: task,
|
||||||
|
Finished: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pcm *PBFTConsensusManager) GetConsensusInfo(consensusID string) *Consensus {
|
||||||
|
c, ok := pcm.consensusMap[consensusID]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
72
consensus/consensus_test.go
Normal file
72
consensus/consensus_test.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package consensus
|
||||||
|
|
||||||
|
import (
|
||||||
|
crand "crypto/rand"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/Secured-Finance/dione/config"
|
||||||
|
"github.com/Secured-Finance/dione/node"
|
||||||
|
crypto "github.com/libp2p/go-libp2p-crypto"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConsensus(t *testing.T) {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|
||||||
|
// setting up nodes
|
||||||
|
port := rand.Intn(100) + 10000
|
||||||
|
|
||||||
|
cfg := &config.Config{
|
||||||
|
ListenPort: port,
|
||||||
|
ListenAddr: "0.0.0.0",
|
||||||
|
Rendezvous: "dione",
|
||||||
|
PubSub: config.PubSubConfig{
|
||||||
|
ProtocolID: "/dione/1.0",
|
||||||
|
},
|
||||||
|
ConsensusMinApprovals: 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
var nodes []*node.Node
|
||||||
|
|
||||||
|
bNode := newNode(cfg)
|
||||||
|
t.Logf("Bootstrap ID: %s", bNode.Host.ID())
|
||||||
|
cfg.BootstrapNodes = []string{bNode.Host.Addrs()[0].String() + fmt.Sprintf("/p2p/%s", bNode.Host.ID().String())}
|
||||||
|
nodes = append(nodes, bNode)
|
||||||
|
|
||||||
|
maxNodes := 10
|
||||||
|
|
||||||
|
for i := 1; i <= maxNodes; i++ {
|
||||||
|
cfg.ListenPort++
|
||||||
|
node := newNode(cfg)
|
||||||
|
nodes = append(nodes, node)
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func newNode(cfg *config.Config) *node.Node {
|
||||||
|
privKey, err := generatePrivateKey()
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
node, err := node.NewNode(cfg, privKey, 1*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
func generatePrivateKey() (crypto.PrivKey, error) {
|
||||||
|
r := crand.Reader
|
||||||
|
// Creates a new RSA key pair for this host.
|
||||||
|
prvKey, _, err := crypto.GenerateKeyPairWithReader(crypto.Ed25519, 2048, r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return prvKey, nil
|
||||||
|
}
|
154
consensus/dispute_manager.go
Normal file
154
consensus/dispute_manager.go
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
package consensus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/Secured-Finance/dione/contracts/dioneDispute"
|
||||||
|
"github.com/Secured-Finance/dione/contracts/dioneOracle"
|
||||||
|
"github.com/Secured-Finance/dione/ethclient"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/crypto/sha3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DisputeManager struct {
|
||||||
|
ctx context.Context
|
||||||
|
ethClient *ethclient.EthereumClient
|
||||||
|
pcm *PBFTConsensusManager
|
||||||
|
submittionMap map[string]*dioneOracle.DioneOracleSubmittedOracleRequest
|
||||||
|
disputeMap map[string]*dioneDispute.DioneDisputeNewDispute
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDisputeManager(ctx context.Context, ethClient *ethclient.EthereumClient, pcm *PBFTConsensusManager) (*DisputeManager, error) {
|
||||||
|
newSubmittionsChan, submSubscription, err := ethClient.SubscribeOnNewSubmittions(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
newDisputesChan, dispSubscription, err := ethClient.SubscribeOnNewDisputes(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
dm := &DisputeManager{
|
||||||
|
ethClient: ethClient,
|
||||||
|
pcm: pcm,
|
||||||
|
ctx: ctx,
|
||||||
|
submittionMap: map[string]*dioneOracle.DioneOracleSubmittedOracleRequest{},
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
{
|
||||||
|
submSubscription.Unsubscribe()
|
||||||
|
dispSubscription.Unsubscribe()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case s := <-newSubmittionsChan:
|
||||||
|
{
|
||||||
|
dm.onNewSubmittion(s)
|
||||||
|
}
|
||||||
|
case d := <-newDisputesChan:
|
||||||
|
{
|
||||||
|
dm.onNewDispute(d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return dm, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dm *DisputeManager) onNewSubmittion(submittion *dioneOracle.DioneOracleSubmittedOracleRequest) {
|
||||||
|
c := dm.pcm.GetConsensusInfo(submittion.ReqID.String())
|
||||||
|
if c == nil {
|
||||||
|
// todo: warn
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dm.submittionMap[submittion.ReqID.String()] = submittion
|
||||||
|
|
||||||
|
submHashBytes := sha3.Sum256(submittion.Data)
|
||||||
|
localHashBytes := sha3.Sum256(c.Task.Payload)
|
||||||
|
submHash := hex.EncodeToString(submHashBytes[:])
|
||||||
|
localHash := hex.EncodeToString(localHashBytes[:])
|
||||||
|
if submHash != localHash {
|
||||||
|
addr := common.HexToAddress(c.Task.MinerEth)
|
||||||
|
reqID, ok := big.NewInt(0).SetString(c.Task.RequestID, 10)
|
||||||
|
if !ok {
|
||||||
|
logrus.Errorf("cannot parse request id: %s", c.Task.RequestID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := dm.ethClient.BeginDispute(addr, reqID)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
disputeFinishTimer := time.NewTimer(time.Minute * 5)
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-dm.ctx.Done():
|
||||||
|
return
|
||||||
|
case <-disputeFinishTimer.C:
|
||||||
|
{
|
||||||
|
d, ok := dm.disputeMap[reqID.String()]
|
||||||
|
if !ok {
|
||||||
|
logrus.Error("cannot finish dispute: it doesn't exist in manager's dispute map!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := dm.ethClient.FinishDispute(d.Dhash)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dm *DisputeManager) onNewDispute(dispute *dioneDispute.DioneDisputeNewDispute) {
|
||||||
|
c := dm.pcm.GetConsensusInfo(dispute.RequestID.String())
|
||||||
|
if c == nil {
|
||||||
|
// todo: warn
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
subm, ok := dm.submittionMap[dispute.RequestID.String()]
|
||||||
|
if !ok {
|
||||||
|
// todo: warn
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dm.disputeMap[dispute.RequestID.String()] = dispute
|
||||||
|
|
||||||
|
if dispute.DisputeInitiator.Hex() == dm.ethClient.GetEthAddress().Hex() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
submHashBytes := sha3.Sum256(subm.Data)
|
||||||
|
localHashBytes := sha3.Sum256(c.Task.Payload)
|
||||||
|
submHash := hex.EncodeToString(submHashBytes[:])
|
||||||
|
localHash := hex.EncodeToString(localHashBytes[:])
|
||||||
|
if submHash == localHash {
|
||||||
|
err := dm.ethClient.VoteDispute(dispute.Dhash, false)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := dm.ethClient.VoteDispute(dispute.Dhash, true)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
@ -34,16 +34,16 @@ func NewPrePreparePool(miner *Miner, evc cache.EventCache) *PrePreparePool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pp *PrePreparePool) CreatePrePrepare(consensusID string, task types.DioneTask, requestID string, callbackAddress, callbackMethodID, privateKey []byte) (*types2.Message, error) {
|
func (pp *PrePreparePool) CreatePrePrepare(task *types.DioneTask, requestID string, callbackAddress, callbackMethodID, privateKey []byte) (*types2.Message, error) {
|
||||||
var message types2.Message
|
var message types2.Message
|
||||||
message.Type = types2.MessageTypePrePrepare
|
message.Type = types2.MessageTypePrePrepare
|
||||||
var consensusMsg types2.ConsensusMessage
|
var consensusMsg types2.ConsensusMessage
|
||||||
consensusMsg.ConsensusID = consensusID
|
consensusMsg.Task.ConsensusID = requestID
|
||||||
consensusMsg.RequestID = requestID
|
consensusMsg.Task.RequestID = requestID
|
||||||
consensusMsg.CallbackAddress = callbackAddress
|
consensusMsg.Task.CallbackAddress = callbackAddress
|
||||||
consensusMsg.CallbackMethodID = callbackMethodID
|
consensusMsg.Task.CallbackMethodID = callbackMethodID
|
||||||
consensusMsg.Task = task
|
consensusMsg.Task = *task
|
||||||
cHash, err := hashstructure.Hash(consensusMsg, hashstructure.FormatV2, nil)
|
cHash, err := hashstructure.Hash(task, hashstructure.FormatV2, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -51,7 +51,7 @@ func (pp *PrePreparePool) CreatePrePrepare(consensusID string, task types.DioneT
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
consensusMsg.Signature = signature.Data
|
consensusMsg.Task.Signature = signature.Data
|
||||||
message.Payload = consensusMsg
|
message.Payload = consensusMsg
|
||||||
return &message, nil
|
return &message, nil
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ func (ppp *PrePreparePool) IsExistingPrePrepare(prepareMsg *types2.Message) bool
|
|||||||
|
|
||||||
consensusMessage := prepareMsg.Payload
|
consensusMessage := prepareMsg.Payload
|
||||||
var exists bool
|
var exists bool
|
||||||
for _, v := range ppp.prePrepareMsgs[consensusMessage.ConsensusID] {
|
for _, v := range ppp.prePrepareMsgs[consensusMessage.Task.ConsensusID] {
|
||||||
if v.From == prepareMsg.From {
|
if v.From == prepareMsg.From {
|
||||||
exists = true
|
exists = true
|
||||||
}
|
}
|
||||||
@ -83,13 +83,13 @@ func (ppp *PrePreparePool) IsValidPrePrepare(prePrepare *types2.Message) bool {
|
|||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
|
|
||||||
// === verify if request exists in event log cache ===
|
// === verify if request exists in event log cache ===
|
||||||
requestEvent, err := ppp.eventLogCache.GetOracleRequestEvent("request_" + consensusMsg.RequestID)
|
requestEvent, err := ppp.eventLogCache.GetOracleRequestEvent("request_" + consensusMsg.Task.RequestID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("the incoming request task event doesn't exist in the EVC, or is broken: %v", err)
|
logrus.Errorf("the incoming request task event doesn't exist in the EVC, or is broken: %v", err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if bytes.Compare(requestEvent.CallbackAddress.Bytes(), consensusMsg.CallbackAddress) != 0 ||
|
if bytes.Compare(requestEvent.CallbackAddress.Bytes(), consensusMsg.Task.CallbackAddress) != 0 ||
|
||||||
bytes.Compare(requestEvent.CallbackMethodID[:], consensusMsg.CallbackMethodID) != 0 ||
|
bytes.Compare(requestEvent.CallbackMethodID[:], consensusMsg.Task.CallbackMethodID) != 0 ||
|
||||||
requestEvent.OriginChain != consensusMsg.Task.OriginChain ||
|
requestEvent.OriginChain != consensusMsg.Task.OriginChain ||
|
||||||
requestEvent.RequestType != consensusMsg.Task.RequestType ||
|
requestEvent.RequestType != consensusMsg.Task.RequestType ||
|
||||||
requestEvent.RequestParams != consensusMsg.Task.RequestParams {
|
requestEvent.RequestParams != consensusMsg.Task.RequestParams {
|
||||||
@ -185,7 +185,7 @@ func (ppp *PrePreparePool) AddPrePrepare(prePrepare *types2.Message) {
|
|||||||
ppp.mut.Lock()
|
ppp.mut.Lock()
|
||||||
defer ppp.mut.Unlock()
|
defer ppp.mut.Unlock()
|
||||||
|
|
||||||
consensusID := prePrepare.Payload.ConsensusID
|
consensusID := prePrepare.Payload.Task.ConsensusID
|
||||||
if _, ok := ppp.prePrepareMsgs[consensusID]; !ok {
|
if _, ok := ppp.prePrepareMsgs[consensusID]; !ok {
|
||||||
ppp.prePrepareMsgs[consensusID] = []*types2.Message{}
|
ppp.prePrepareMsgs[consensusID] = []*types2.Message{}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ func (pp *PreparePool) IsExistingPrepare(prepareMsg *types2.Message) bool {
|
|||||||
|
|
||||||
consensusMessage := prepareMsg.Payload
|
consensusMessage := prepareMsg.Payload
|
||||||
var exists bool
|
var exists bool
|
||||||
for _, v := range pp.prepareMsgs[consensusMessage.ConsensusID] {
|
for _, v := range pp.prepareMsgs[consensusMessage.Task.ConsensusID] {
|
||||||
if v.From == prepareMsg.From {
|
if v.From == prepareMsg.From {
|
||||||
exists = true
|
exists = true
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ func (pp *PreparePool) AddPrepare(prepare *types2.Message) {
|
|||||||
pp.mut.Lock()
|
pp.mut.Lock()
|
||||||
defer pp.mut.Unlock()
|
defer pp.mut.Unlock()
|
||||||
|
|
||||||
consensusID := prepare.Payload.ConsensusID
|
consensusID := prepare.Payload.Task.ConsensusID
|
||||||
if _, ok := pp.prepareMsgs[consensusID]; !ok {
|
if _, ok := pp.prepareMsgs[consensusID]; !ok {
|
||||||
pp.prepareMsgs[consensusID] = []*types2.Message{}
|
pp.prepareMsgs[consensusID] = []*types2.Message{}
|
||||||
}
|
}
|
||||||
|
@ -16,12 +16,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ConsensusMessage struct {
|
type ConsensusMessage struct {
|
||||||
ConsensusID string
|
Task types.DioneTask
|
||||||
Signature []byte `hash:"-"`
|
|
||||||
RequestID string
|
|
||||||
CallbackAddress []byte
|
|
||||||
CallbackMethodID []byte
|
|
||||||
Task types.DioneTask
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
|
@ -15,7 +15,7 @@ func verifyTaskSignature(msg types.ConsensusMessage) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = sigs.Verify(
|
err = sigs.Verify(
|
||||||
&types2.Signature{Type: types2.SigTypeEd25519, Data: msg.Signature},
|
&types2.Signature{Type: types2.SigTypeEd25519, Data: msg.Task.Signature},
|
||||||
[]byte(msg.Task.Miner),
|
[]byte(msg.Task.Miner),
|
||||||
[]byte(fmt.Sprintf("%v", cHash)),
|
[]byte(fmt.Sprintf("%v", cHash)),
|
||||||
)
|
)
|
||||||
|
@ -27,7 +27,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// DioneDisputeABI is the input ABI used to generate the binding from.
|
// DioneDisputeABI is the input ABI used to generate the binding from.
|
||||||
const DioneDisputeABI = "[{\"inputs\":[{\"internalType\":\"contractIDioneStaking\",\"name\":\"_dioneStaking\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"dhash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"status\",\"type\":\"bool\"}],\"name\":\"DisputeFinished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"dhash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"miner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"disputeInitiator\",\"type\":\"address\"}],\"name\":\"NewDispute\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"dhash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"votedMiner\",\"type\":\"address\"}],\"name\":\"NewVote\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"dioneStaking\",\"outputs\":[{\"internalType\":\"contractIDioneStaking\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"miner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"}],\"name\":\"beginDispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dhash\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"voteStatus\",\"type\":\"bool\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dhash\",\"type\":\"bytes32\"}],\"name\":\"finishDispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],"
|
const DioneDisputeABI = "[{\"inputs\":[{\"internalType\":\"contractIDioneStaking\",\"name\":\"_dioneStaking\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"dhash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"status\",\"type\":\"bool\"}],\"name\":\"DisputeFinished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"dhash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"miner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"disputeInitiator\",\"type\":\"address\"}],\"name\":\"NewDispute\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"dhash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"votedMiner\",\"type\":\"address\"}],\"name\":\"NewVote\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"dioneStaking\",\"outputs\":[{\"internalType\":\"contractIDioneStaking\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"miner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"}],\"name\":\"beginDispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dhash\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"voteStatus\",\"type\":\"bool\"}],\"name\":\"vote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dhash\",\"type\":\"bytes32\"}],\"name\":\"finishDispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"
|
||||||
|
|
||||||
// DioneDispute is an auto generated Go binding around an Ethereum contract.
|
// DioneDispute is an auto generated Go binding around an Ethereum contract.
|
||||||
type DioneDispute struct {
|
type DioneDispute struct {
|
||||||
@ -470,14 +470,15 @@ func (it *DioneDisputeNewDisputeIterator) Close() error {
|
|||||||
// DioneDisputeNewDispute represents a NewDispute event raised by the DioneDispute contract.
|
// DioneDisputeNewDispute represents a NewDispute event raised by the DioneDispute contract.
|
||||||
type DioneDisputeNewDispute struct {
|
type DioneDisputeNewDispute struct {
|
||||||
Dhash [32]byte
|
Dhash [32]byte
|
||||||
|
RequestID *big.Int
|
||||||
Miner common.Address
|
Miner common.Address
|
||||||
DisputeInitiator common.Address
|
DisputeInitiator common.Address
|
||||||
Raw types.Log // Blockchain specific contextual infos
|
Raw types.Log // Blockchain specific contextual infos
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterNewDispute is a free log retrieval operation binding the contract event 0xcd3d2ebd72bbbf7e5659c6790b60f42174aafe2741b7ba3807007455faae522e.
|
// FilterNewDispute is a free log retrieval operation binding the contract event 0x2ce1dcf0fdc2fa2126a7df604e89d10856ef74891a365a93e779a5c4aff5370a.
|
||||||
//
|
//
|
||||||
// Solidity: event NewDispute(bytes32 dhash, address indexed miner, address indexed disputeInitiator)
|
// Solidity: event NewDispute(bytes32 dhash, uint256 requestID, address indexed miner, address indexed disputeInitiator)
|
||||||
func (_DioneDispute *DioneDisputeFilterer) FilterNewDispute(opts *bind.FilterOpts, miner []common.Address, disputeInitiator []common.Address) (*DioneDisputeNewDisputeIterator, error) {
|
func (_DioneDispute *DioneDisputeFilterer) FilterNewDispute(opts *bind.FilterOpts, miner []common.Address, disputeInitiator []common.Address) (*DioneDisputeNewDisputeIterator, error) {
|
||||||
|
|
||||||
var minerRule []interface{}
|
var minerRule []interface{}
|
||||||
@ -496,9 +497,9 @@ func (_DioneDispute *DioneDisputeFilterer) FilterNewDispute(opts *bind.FilterOpt
|
|||||||
return &DioneDisputeNewDisputeIterator{contract: _DioneDispute.contract, event: "NewDispute", logs: logs, sub: sub}, nil
|
return &DioneDisputeNewDisputeIterator{contract: _DioneDispute.contract, event: "NewDispute", logs: logs, sub: sub}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WatchNewDispute is a free log subscription operation binding the contract event 0xcd3d2ebd72bbbf7e5659c6790b60f42174aafe2741b7ba3807007455faae522e.
|
// WatchNewDispute is a free log subscription operation binding the contract event 0x2ce1dcf0fdc2fa2126a7df604e89d10856ef74891a365a93e779a5c4aff5370a.
|
||||||
//
|
//
|
||||||
// Solidity: event NewDispute(bytes32 dhash, address indexed miner, address indexed disputeInitiator)
|
// Solidity: event NewDispute(bytes32 dhash, uint256 requestID, address indexed miner, address indexed disputeInitiator)
|
||||||
func (_DioneDispute *DioneDisputeFilterer) WatchNewDispute(opts *bind.WatchOpts, sink chan<- *DioneDisputeNewDispute, miner []common.Address, disputeInitiator []common.Address) (event.Subscription, error) {
|
func (_DioneDispute *DioneDisputeFilterer) WatchNewDispute(opts *bind.WatchOpts, sink chan<- *DioneDisputeNewDispute, miner []common.Address, disputeInitiator []common.Address) (event.Subscription, error) {
|
||||||
|
|
||||||
var minerRule []interface{}
|
var minerRule []interface{}
|
||||||
@ -542,9 +543,9 @@ func (_DioneDispute *DioneDisputeFilterer) WatchNewDispute(opts *bind.WatchOpts,
|
|||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseNewDispute is a log parse operation binding the contract event 0xcd3d2ebd72bbbf7e5659c6790b60f42174aafe2741b7ba3807007455faae522e.
|
// ParseNewDispute is a log parse operation binding the contract event 0x2ce1dcf0fdc2fa2126a7df604e89d10856ef74891a365a93e779a5c4aff5370a.
|
||||||
//
|
//
|
||||||
// Solidity: event NewDispute(bytes32 dhash, address indexed miner, address indexed disputeInitiator)
|
// Solidity: event NewDispute(bytes32 dhash, uint256 requestID, address indexed miner, address indexed disputeInitiator)
|
||||||
func (_DioneDispute *DioneDisputeFilterer) ParseNewDispute(log types.Log) (*DioneDisputeNewDispute, error) {
|
func (_DioneDispute *DioneDisputeFilterer) ParseNewDispute(log types.Log) (*DioneDisputeNewDispute, error) {
|
||||||
event := new(DioneDisputeNewDispute)
|
event := new(DioneDisputeNewDispute)
|
||||||
if err := _DioneDispute.contract.UnpackLog(event, "NewDispute", log); err != nil {
|
if err := _DioneDispute.contract.UnpackLog(event, "NewDispute", log); err != nil {
|
||||||
|
@ -21,7 +21,7 @@ contract DioneDispute {
|
|||||||
|
|
||||||
mapping(bytes32 => Dispute) disputes;
|
mapping(bytes32 => Dispute) disputes;
|
||||||
|
|
||||||
event NewDispute(bytes32 dhash, address indexed miner, address indexed disputeInitiator);
|
event NewDispute(bytes32 dhash, uint256 requestID, address indexed miner, address indexed disputeInitiator);
|
||||||
event NewVote(bytes32 dhash, address indexed votedMiner);
|
event NewVote(bytes32 dhash, address indexed votedMiner);
|
||||||
event DisputeFinished(bytes32 dhash, bool status);
|
event DisputeFinished(bytes32 dhash, bool status);
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ contract DioneDispute {
|
|||||||
|
|
||||||
disputes[dhash] = dispute;
|
disputes[dhash] = dispute;
|
||||||
|
|
||||||
emit NewDispute(dhash, miner, msg.sender);
|
emit NewDispute(dhash, requestID, miner, msg.sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
function vote(bytes32 dhash, bool voteStatus) public {
|
function vote(bytes32 dhash, bool voteStatus) public {
|
||||||
|
@ -2,7 +2,6 @@ package ethclient
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/Secured-Finance/dione/contracts/dioneDispute"
|
"github.com/Secured-Finance/dione/contracts/dioneDispute"
|
||||||
@ -158,14 +157,8 @@ func (c *EthereumClient) BeginDispute(miner common.Address, requestID *big.Int)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *EthereumClient) VoteDispute(dhash string, voteStatus bool) error {
|
func (c *EthereumClient) VoteDispute(dhash [32]byte, voteStatus bool) error {
|
||||||
dhashRawSlice, err := hex.DecodeString(dhash)
|
_, err := c.disputeContract.Vote(dhash, voteStatus)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var dhashRaw [32]byte
|
|
||||||
copy(dhashRaw[:], dhashRawSlice)
|
|
||||||
_, err = c.disputeContract.Vote(dhashRaw, voteStatus)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -173,14 +166,8 @@ func (c *EthereumClient) VoteDispute(dhash string, voteStatus bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *EthereumClient) FinishDispute(dhash string) error {
|
func (c *EthereumClient) FinishDispute(dhash [32]byte) error {
|
||||||
dhashRawSlice, err := hex.DecodeString(dhash)
|
_, err := c.disputeContract.FinishDispute(dhash)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var dhashRaw [32]byte
|
|
||||||
copy(dhashRaw[:], dhashRawSlice)
|
|
||||||
_, err = c.disputeContract.FinishDispute(dhashRaw)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -205,7 +192,7 @@ func (c *EthereumClient) SubscribeOnNewSubmittions(ctx context.Context) (chan *d
|
|||||||
resChan := make(chan *dioneOracle.DioneOracleSubmittedOracleRequest)
|
resChan := make(chan *dioneOracle.DioneOracleSubmittedOracleRequest)
|
||||||
requestsFilter := c.dioneOracle.Contract.DioneOracleFilterer
|
requestsFilter := c.dioneOracle.Contract.DioneOracleFilterer
|
||||||
subscription, err := requestsFilter.WatchSubmittedOracleRequest(&bind.WatchOpts{
|
subscription, err := requestsFilter.WatchSubmittedOracleRequest(&bind.WatchOpts{
|
||||||
Start: nil, //last block
|
Start: nil, // last block
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
}, resChan)
|
}, resChan)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -19,16 +19,21 @@ func (e DrandRound) String() string {
|
|||||||
|
|
||||||
// DioneTask represents the values of task computation
|
// DioneTask represents the values of task computation
|
||||||
type DioneTask struct {
|
type DioneTask struct {
|
||||||
OriginChain uint8
|
OriginChain uint8
|
||||||
RequestType string
|
RequestType string
|
||||||
RequestParams string
|
RequestParams string
|
||||||
Miner peer.ID
|
Miner peer.ID
|
||||||
MinerEth string
|
MinerEth string
|
||||||
Ticket *Ticket
|
Ticket *Ticket
|
||||||
ElectionProof *ElectionProof
|
ElectionProof *ElectionProof
|
||||||
BeaconEntries []BeaconEntry
|
BeaconEntries []BeaconEntry
|
||||||
DrandRound DrandRound
|
DrandRound DrandRound
|
||||||
Payload []byte
|
Payload []byte
|
||||||
|
RequestID string
|
||||||
|
CallbackAddress []byte
|
||||||
|
CallbackMethodID []byte
|
||||||
|
ConsensusID string
|
||||||
|
Signature []byte `hash:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDioneTask(
|
func NewDioneTask(
|
||||||
|
Loading…
Reference in New Issue
Block a user