diff --git a/consensus/commit_pool.go b/consensus/commit_pool.go index bc4ff24..54a41ea 100644 --- a/consensus/commit_pool.go +++ b/consensus/commit_pool.go @@ -32,7 +32,7 @@ func (cp *CommitPool) IsExistingCommit(commitMsg *types2.Message) bool { consensusMessage := commitMsg.Payload var exists bool - for _, v := range cp.commitMsgs[consensusMessage.ConsensusID] { + for _, v := range cp.commitMsgs[consensusMessage.Task.ConsensusID] { if v.From == commitMsg.From { exists = true } @@ -54,7 +54,7 @@ func (cp *CommitPool) AddCommit(commit *types2.Message) { cp.mut.Lock() defer cp.mut.Unlock() - consensusID := commit.Payload.ConsensusID + consensusID := commit.Payload.Task.ConsensusID if _, ok := cp.commitMsgs[consensusID]; !ok { cp.commitMsgs[consensusID] = []*types2.Message{} } diff --git a/consensus/consensus.go b/consensus/consensus.go index beaa38f..1f21b93 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -26,15 +26,17 @@ type PBFTConsensusManager struct { prePreparePool *PrePreparePool preparePool *PreparePool commitPool *CommitPool - consensusInfo map[string]*ConsensusData + consensusMap map[string]*Consensus ethereumClient *ethclient.EthereumClient miner *Miner eventCache cache.EventCache } -type ConsensusData struct { - mutex sync.Mutex - alreadySubmitted bool +type Consensus struct { + mutex sync.Mutex + 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 { @@ -48,7 +50,7 @@ func NewPBFTConsensusManager(psb *pubsub.PubSubRouter, minApprovals int, privKey pcm.privKey = privKey pcm.ethereumClient = ethereumClient pcm.eventCache = evc - pcm.consensusInfo = map[string]*ConsensusData{} + pcm.consensusMap = map[string]*Consensus{} pcm.psb.Hook(types.MessageTypePrePrepare, pcm.handlePrePrepare) pcm.psb.Hook(types.MessageTypePrepare, pcm.handlePrepare) 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 { - pcm.consensusInfo[consensusID] = &ConsensusData{} + pcm.createConsensusInfo(&task, true) prePrepareMsg, err := pcm.prePreparePool.CreatePrePrepare( - consensusID, - task, + &task, requestEvent.ReqID.String(), requestEvent.CallbackAddress.Bytes(), requestEvent.CallbackMethodID[:], @@ -74,6 +75,9 @@ func (pcm *PBFTConsensusManager) Propose(consensusID string, task types2.DioneTa } func (pcm *PBFTConsensusManager) handlePrePrepare(message *types.Message) { + if message.Payload.Task.Miner == pcm.miner.address { + return + } if pcm.prePreparePool.IsExistingPrePrepare(message) { logrus.Debug("received existing pre_prepare msg, dropping...") return @@ -94,6 +98,9 @@ func (pcm *PBFTConsensusManager) handlePrePrepare(message *types.Message) { if err != nil { logrus.Errorf("failed to create prepare message: %w", err) } + + pcm.createConsensusInfo(&message.Payload.Task, false) + pcm.psb.BroadcastToServiceTopic(prepareMsg) } @@ -114,7 +121,7 @@ func (pcm *PBFTConsensusManager) handlePrepare(message *types.Message) { 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) if err != nil { logrus.Errorf("failed to create commit message: %w", err) @@ -141,21 +148,22 @@ func (pcm *PBFTConsensusManager) handleCommit(message *types.Message) { } consensusMsg := message.Payload - if pcm.commitPool.CommitSize(consensusMsg.ConsensusID) >= pcm.minApprovals { - if info, ok := pcm.consensusInfo[consensusMsg.ConsensusID]; ok { - info.mutex.Lock() - defer info.mutex.Unlock() - if info.alreadySubmitted { - return - } - logrus.Infof("Submitting on-chain result for consensus ID: %s", consensusMsg.ConsensusID) - reqID, ok := new(big.Int).SetString(consensusMsg.RequestID, 10) + if pcm.commitPool.CommitSize(consensusMsg.Task.ConsensusID) >= pcm.minApprovals { + info := pcm.consensusMap[consensusMsg.Task.ConsensusID] + info.mutex.Lock() + defer info.mutex.Unlock() + if info.Finished { + return + } + if info.IsCurrentMinerLeader { + 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 { - 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 { logrus.Errorf("Failed to get request from cache: %v", err.Error()) return @@ -165,7 +173,25 @@ func (pcm *PBFTConsensusManager) handleCommit(message *types.Message) { if err != nil { 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 +} diff --git a/consensus/consensus_test.go b/consensus/consensus_test.go new file mode 100644 index 0000000..55af778 --- /dev/null +++ b/consensus/consensus_test.go @@ -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 +} diff --git a/consensus/dispute_manager.go b/consensus/dispute_manager.go new file mode 100644 index 0000000..40a8e84 --- /dev/null +++ b/consensus/dispute_manager.go @@ -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 + } +} diff --git a/consensus/pre_prepare_pool.go b/consensus/pre_prepare_pool.go index c2a2622..ccd7f64 100644 --- a/consensus/pre_prepare_pool.go +++ b/consensus/pre_prepare_pool.go @@ -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 message.Type = types2.MessageTypePrePrepare var consensusMsg types2.ConsensusMessage - consensusMsg.ConsensusID = consensusID - consensusMsg.RequestID = requestID - consensusMsg.CallbackAddress = callbackAddress - consensusMsg.CallbackMethodID = callbackMethodID - consensusMsg.Task = task - cHash, err := hashstructure.Hash(consensusMsg, hashstructure.FormatV2, nil) + consensusMsg.Task.ConsensusID = requestID + consensusMsg.Task.RequestID = requestID + consensusMsg.Task.CallbackAddress = callbackAddress + consensusMsg.Task.CallbackMethodID = callbackMethodID + consensusMsg.Task = *task + cHash, err := hashstructure.Hash(task, hashstructure.FormatV2, nil) if err != nil { return nil, err } @@ -51,7 +51,7 @@ func (pp *PrePreparePool) CreatePrePrepare(consensusID string, task types.DioneT if err != nil { return nil, err } - consensusMsg.Signature = signature.Data + consensusMsg.Task.Signature = signature.Data message.Payload = consensusMsg return &message, nil } @@ -62,7 +62,7 @@ func (ppp *PrePreparePool) IsExistingPrePrepare(prepareMsg *types2.Message) bool consensusMessage := prepareMsg.Payload var exists bool - for _, v := range ppp.prePrepareMsgs[consensusMessage.ConsensusID] { + for _, v := range ppp.prePrepareMsgs[consensusMessage.Task.ConsensusID] { if v.From == prepareMsg.From { exists = true } @@ -83,13 +83,13 @@ func (ppp *PrePreparePool) IsValidPrePrepare(prePrepare *types2.Message) bool { ///////////////////////////////// // === 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 { logrus.Errorf("the incoming request task event doesn't exist in the EVC, or is broken: %v", err) return false } - if bytes.Compare(requestEvent.CallbackAddress.Bytes(), consensusMsg.CallbackAddress) != 0 || - bytes.Compare(requestEvent.CallbackMethodID[:], consensusMsg.CallbackMethodID) != 0 || + if bytes.Compare(requestEvent.CallbackAddress.Bytes(), consensusMsg.Task.CallbackAddress) != 0 || + bytes.Compare(requestEvent.CallbackMethodID[:], consensusMsg.Task.CallbackMethodID) != 0 || requestEvent.OriginChain != consensusMsg.Task.OriginChain || requestEvent.RequestType != consensusMsg.Task.RequestType || requestEvent.RequestParams != consensusMsg.Task.RequestParams { @@ -185,7 +185,7 @@ func (ppp *PrePreparePool) AddPrePrepare(prePrepare *types2.Message) { ppp.mut.Lock() defer ppp.mut.Unlock() - consensusID := prePrepare.Payload.ConsensusID + consensusID := prePrepare.Payload.Task.ConsensusID if _, ok := ppp.prePrepareMsgs[consensusID]; !ok { ppp.prePrepareMsgs[consensusID] = []*types2.Message{} } diff --git a/consensus/prepare_pool.go b/consensus/prepare_pool.go index 180184e..0425ab8 100644 --- a/consensus/prepare_pool.go +++ b/consensus/prepare_pool.go @@ -32,7 +32,7 @@ func (pp *PreparePool) IsExistingPrepare(prepareMsg *types2.Message) bool { consensusMessage := prepareMsg.Payload var exists bool - for _, v := range pp.prepareMsgs[consensusMessage.ConsensusID] { + for _, v := range pp.prepareMsgs[consensusMessage.Task.ConsensusID] { if v.From == prepareMsg.From { exists = true } @@ -53,7 +53,7 @@ func (pp *PreparePool) AddPrepare(prepare *types2.Message) { pp.mut.Lock() defer pp.mut.Unlock() - consensusID := prepare.Payload.ConsensusID + consensusID := prepare.Payload.Task.ConsensusID if _, ok := pp.prepareMsgs[consensusID]; !ok { pp.prepareMsgs[consensusID] = []*types2.Message{} } diff --git a/consensus/types/message.go b/consensus/types/message.go index 7b6284a..b2995e9 100644 --- a/consensus/types/message.go +++ b/consensus/types/message.go @@ -16,12 +16,7 @@ const ( ) type ConsensusMessage struct { - ConsensusID string - Signature []byte `hash:"-"` - RequestID string - CallbackAddress []byte - CallbackMethodID []byte - Task types.DioneTask + Task types.DioneTask } type Message struct { diff --git a/consensus/utils.go b/consensus/utils.go index d0a4564..62895e1 100644 --- a/consensus/utils.go +++ b/consensus/utils.go @@ -15,7 +15,7 @@ func verifyTaskSignature(msg types.ConsensusMessage) error { return err } 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(fmt.Sprintf("%v", cHash)), ) diff --git a/contracts/dioneDispute/dione_dispute.go b/contracts/dioneDispute/dione_dispute.go index eff6c4b..9c7b0ca 100644 --- a/contracts/dioneDispute/dione_dispute.go +++ b/contracts/dioneDispute/dione_dispute.go @@ -27,7 +27,7 @@ var ( ) // 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. type DioneDispute struct { @@ -470,14 +470,15 @@ func (it *DioneDisputeNewDisputeIterator) Close() error { // DioneDisputeNewDispute represents a NewDispute event raised by the DioneDispute contract. type DioneDisputeNewDispute struct { Dhash [32]byte + RequestID *big.Int Miner common.Address DisputeInitiator common.Address 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) { 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 } -// 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) { var minerRule []interface{} @@ -542,9 +543,9 @@ func (_DioneDispute *DioneDisputeFilterer) WatchNewDispute(opts *bind.WatchOpts, }), 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) { event := new(DioneDisputeNewDispute) if err := _DioneDispute.contract.UnpackLog(event, "NewDispute", log); err != nil { diff --git a/eth-contracts/contracts/DioneDispute.sol b/eth-contracts/contracts/DioneDispute.sol index 5c5eece..2ad9f40 100644 --- a/eth-contracts/contracts/DioneDispute.sol +++ b/eth-contracts/contracts/DioneDispute.sol @@ -21,7 +21,7 @@ contract DioneDispute { 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 DisputeFinished(bytes32 dhash, bool status); @@ -43,7 +43,7 @@ contract DioneDispute { disputes[dhash] = dispute; - emit NewDispute(dhash, miner, msg.sender); + emit NewDispute(dhash, requestID, miner, msg.sender); } function vote(bytes32 dhash, bool voteStatus) public { diff --git a/ethclient/ethereum.go b/ethclient/ethereum.go index e8b06b4..454975b 100644 --- a/ethclient/ethereum.go +++ b/ethclient/ethereum.go @@ -2,7 +2,6 @@ package ethclient import ( "context" - "encoding/hex" "math/big" "github.com/Secured-Finance/dione/contracts/dioneDispute" @@ -158,14 +157,8 @@ func (c *EthereumClient) BeginDispute(miner common.Address, requestID *big.Int) return nil } -func (c *EthereumClient) VoteDispute(dhash string, voteStatus bool) error { - dhashRawSlice, err := hex.DecodeString(dhash) - if err != nil { - return err - } - var dhashRaw [32]byte - copy(dhashRaw[:], dhashRawSlice) - _, err = c.disputeContract.Vote(dhashRaw, voteStatus) +func (c *EthereumClient) VoteDispute(dhash [32]byte, voteStatus bool) error { + _, err := c.disputeContract.Vote(dhash, voteStatus) if err != nil { return err } @@ -173,14 +166,8 @@ func (c *EthereumClient) VoteDispute(dhash string, voteStatus bool) error { return nil } -func (c *EthereumClient) FinishDispute(dhash string) error { - dhashRawSlice, err := hex.DecodeString(dhash) - if err != nil { - return err - } - var dhashRaw [32]byte - copy(dhashRaw[:], dhashRawSlice) - _, err = c.disputeContract.FinishDispute(dhashRaw) +func (c *EthereumClient) FinishDispute(dhash [32]byte) error { + _, err := c.disputeContract.FinishDispute(dhash) if err != nil { return err } @@ -205,7 +192,7 @@ func (c *EthereumClient) SubscribeOnNewSubmittions(ctx context.Context) (chan *d resChan := make(chan *dioneOracle.DioneOracleSubmittedOracleRequest) requestsFilter := c.dioneOracle.Contract.DioneOracleFilterer subscription, err := requestsFilter.WatchSubmittedOracleRequest(&bind.WatchOpts{ - Start: nil, //last block + Start: nil, // last block Context: ctx, }, resChan) if err != nil { diff --git a/types/task.go b/types/task.go index 3db7f56..c7ede67 100644 --- a/types/task.go +++ b/types/task.go @@ -19,16 +19,21 @@ func (e DrandRound) String() string { // DioneTask represents the values of task computation type DioneTask struct { - OriginChain uint8 - RequestType string - RequestParams string - Miner peer.ID - MinerEth string - Ticket *Ticket - ElectionProof *ElectionProof - BeaconEntries []BeaconEntry - DrandRound DrandRound - Payload []byte + OriginChain uint8 + RequestType string + RequestParams string + Miner peer.ID + MinerEth string + Ticket *Ticket + ElectionProof *ElectionProof + BeaconEntries []BeaconEntry + DrandRound DrandRound + Payload []byte + RequestID string + CallbackAddress []byte + CallbackMethodID []byte + ConsensusID string + Signature []byte `hash:"-"` } func NewDioneTask(