mirror of https://github.com/poanetwork/quorum.git
189 lines
4.9 KiB
Go
189 lines
4.9 KiB
Go
package cluster
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"math/big"
|
|
|
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
|
"github.com/ethereum/go-ethereum/controls"
|
|
pbind "github.com/ethereum/go-ethereum/controls/bind/cluster"
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
"github.com/ethereum/go-ethereum/ethclient"
|
|
"github.com/ethereum/go-ethereum/log"
|
|
"github.com/ethereum/go-ethereum/node"
|
|
"github.com/ethereum/go-ethereum/params"
|
|
)
|
|
|
|
type OrgKeyCtrl struct {
|
|
ethClient *ethclient.Client
|
|
key *ecdsa.PrivateKey
|
|
km *pbind.Cluster
|
|
}
|
|
|
|
// Creates the controls structure for org key management
|
|
func NewOrgKeyCtrl(node *node.Node) (*OrgKeyCtrl, error) {
|
|
stateReader, _, err := controls.CreateEthClient(node)
|
|
if err != nil {
|
|
log.Error("Unable to create ethereum client for cluster check", "err", err)
|
|
return nil, err
|
|
}
|
|
// check if permissioning contract is there at address. If not return from here
|
|
km, err := pbind.NewCluster(params.QuorumPrivateKeyManagementContract, stateReader)
|
|
if err != nil {
|
|
log.Error("Permissions not enabled for the network", "err", err)
|
|
return nil, err
|
|
}
|
|
return &OrgKeyCtrl{stateReader, node.GetNodeKey(), km}, nil
|
|
}
|
|
|
|
// starts the org key management services
|
|
func (k *OrgKeyCtrl) Start() error {
|
|
|
|
_, err := pbind.NewClusterFilterer(params.QuorumPrivateKeyManagementContract, k.ethClient)
|
|
if err != nil {
|
|
log.Error("Cluster not enabled for the network", "err", err)
|
|
return nil
|
|
}
|
|
|
|
// check if permissioning contract is there at address. If not return from here
|
|
err = k.checkIfContractExists()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// start the service
|
|
k.manageClusterKeys()
|
|
return nil
|
|
}
|
|
|
|
// checks if the contract is deployed for org key management
|
|
func (k *OrgKeyCtrl) checkIfContractExists() error {
|
|
auth := bind.NewKeyedTransactor(k.key)
|
|
clusterSession := &pbind.ClusterSession{
|
|
Contract: k.km,
|
|
CallOpts: bind.CallOpts{
|
|
Pending: true,
|
|
},
|
|
TransactOpts: bind.TransactOpts{
|
|
From: auth.From,
|
|
Signer: auth.Signer,
|
|
GasLimit: 4700000,
|
|
GasPrice: big.NewInt(0),
|
|
},
|
|
}
|
|
|
|
// dummy call to contrat to check if the contract is deployed
|
|
_, err := clusterSession.CheckOrgContractExists()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// in case of geth restart firts checks for historical key update events and
|
|
// populates the cache, then starts the key change monitoring service
|
|
func (k *OrgKeyCtrl) manageClusterKeys() {
|
|
//call populate nodes to populate the nodes into contract
|
|
if err := k.populatePrivateKeys(); err != nil {
|
|
return
|
|
}
|
|
//monitor for nodes deletiin via smart contract
|
|
k.monitorKeyChanges()
|
|
}
|
|
|
|
// populates cache based on the historical key change events.
|
|
func (k *OrgKeyCtrl) populatePrivateKeys() error {
|
|
cluster, err := pbind.NewClusterFilterer(params.QuorumPrivateKeyManagementContract, k.ethClient)
|
|
if err != nil {
|
|
log.Error("Failed to monitor node delete", "err", err)
|
|
return err
|
|
}
|
|
|
|
opts := &bind.FilterOpts{}
|
|
pastAddEvents, err := cluster.FilterOrgKeyAdded(opts)
|
|
|
|
if err != nil && err.Error() == "no contract code at given address" {
|
|
return err
|
|
}
|
|
|
|
recExists := true
|
|
for recExists {
|
|
recExists = pastAddEvents.Next()
|
|
if recExists {
|
|
types.AddOrgKey(pastAddEvents.Event.OrgId, pastAddEvents.Event.TmKey)
|
|
}
|
|
}
|
|
|
|
opts = &bind.FilterOpts{}
|
|
pastDeleteEvents, _ := cluster.FilterOrgKeyDeleted(opts)
|
|
|
|
recExists = true
|
|
for recExists {
|
|
recExists = pastDeleteEvents.Next()
|
|
if recExists {
|
|
types.DeleteOrgKey(pastDeleteEvents.Event.OrgId, pastDeleteEvents.Event.TmKey)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// service to monitor key change events
|
|
func (k *OrgKeyCtrl) monitorKeyChanges() {
|
|
go k.monitorKeyAdd()
|
|
|
|
go k.monitorKeyDelete()
|
|
}
|
|
|
|
// monitors for new key added event and updates caches based on the same
|
|
func (k *OrgKeyCtrl) monitorKeyAdd() {
|
|
cluster, err := pbind.NewClusterFilterer(params.QuorumPrivateKeyManagementContract, k.ethClient)
|
|
if err != nil {
|
|
log.Error("Failed to monitor key action", "err", err)
|
|
}
|
|
ch := make(chan *pbind.ClusterOrgKeyAdded)
|
|
|
|
opts := &bind.WatchOpts{}
|
|
var blockNumber uint64 = 1
|
|
opts.Start = &blockNumber
|
|
var newEvent *pbind.ClusterOrgKeyAdded
|
|
|
|
_, err = cluster.WatchOrgKeyAdded(opts, ch)
|
|
if err != nil {
|
|
log.Info("Failed WatchOrgKeyDeleted: %v", err)
|
|
}
|
|
|
|
for {
|
|
select {
|
|
case newEvent = <-ch:
|
|
types.AddOrgKey(newEvent.OrgId, newEvent.TmKey)
|
|
}
|
|
}
|
|
}
|
|
|
|
// monitors for new key delete event and updates caches based on the same
|
|
func (k *OrgKeyCtrl) monitorKeyDelete() {
|
|
cluster, err := pbind.NewClusterFilterer(params.QuorumPrivateKeyManagementContract, k.ethClient)
|
|
if err != nil {
|
|
log.Error("Failed to monitor key action", "err", err)
|
|
}
|
|
ch := make(chan *pbind.ClusterOrgKeyDeleted)
|
|
|
|
opts := &bind.WatchOpts{}
|
|
var blockNumber uint64 = 1
|
|
opts.Start = &blockNumber
|
|
var newEvent *pbind.ClusterOrgKeyDeleted
|
|
|
|
_, err = cluster.WatchOrgKeyDeleted(opts, ch)
|
|
if err != nil {
|
|
log.Info("Failed WatchOrgKeyDeleted: %v", err)
|
|
}
|
|
|
|
for {
|
|
select {
|
|
case newEvent = <-ch:
|
|
types.DeleteOrgKey(newEvent.OrgId, newEvent.TmKey)
|
|
}
|
|
}
|
|
}
|