Implement basic version of dispute manager, slightly refactor consensus package

This commit is contained in:
ChronosX88 2021-03-15 23:39:52 +03:00
parent 56c23a9087
commit 35e7994da7
Signed by: ChronosXYZ
GPG Key ID: 085A69A82C8C511A
12 changed files with 323 additions and 83 deletions

View File

@ -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{}
} }

View File

@ -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
} }

View 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
}

View 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
}
}

View File

@ -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{}
} }

View File

@ -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{}
} }

View File

@ -16,11 +16,6 @@ const (
) )
type ConsensusMessage struct { type ConsensusMessage struct {
ConsensusID string
Signature []byte `hash:"-"`
RequestID string
CallbackAddress []byte
CallbackMethodID []byte
Task types.DioneTask Task types.DioneTask
} }

View File

@ -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)),
) )

View File

@ -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 {

View File

@ -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 {

View File

@ -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
} }

View File

@ -29,6 +29,11 @@ type DioneTask struct {
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(