Skip to content
This repository has been archived by the owner on Jan 3, 2023. It is now read-only.

Mir crypto #208

Merged
merged 18 commits into from
Jun 21, 2022
Merged

Mir crypto #208

merged 18 commits into from
Jun 21, 2022

Conversation

dnkolegov
Copy link
Collaborator

This PR adds an implementation of Mir's Crypto interface.

Copy link
Collaborator

@adlrocha adlrocha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this just a draft, added a few comments. Let me know if you need me to give it a deeper look.

chain/consensus/mir/crypto.go Outdated Show resolved Hide resolved
chain/consensus/mir/crypto.go Outdated Show resolved Hide resolved
Copy link
Contributor

@matejpavlovic matejpavlovic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!
Now that the upgrade to mir is finally merged, the only thing that needs to be implemented is the mirCrypto.Impl interface of Mir.

Then we can use it as a module like this

cryptoManager, err := NewCryptoManager(...)
// handle err...
cryptoModule := mirCrypto.New(cryptoManager)
// ...
// use cryptoModule when instantiating a Node with mir.NewNode(...)

chain/consensus/mir/crypto.go Outdated Show resolved Hide resolved
chain/consensus/mir/crypto.go Outdated Show resolved Hide resolved
@matejpavlovic
Copy link
Contributor

Discussion

Question

What is the VerifyClientSig function and do we need it? How is it different from VerifyNodeSig?

Answer

It is meant for verifying signatures on transactions in an SMR system. In Eudico-terms, this would be for verifying signatures on Eudico messages that were produced using a wallet key.

On the other hand, the VerifyNodeSig function verifies signatures on some protocol messages. These signatures are created explicitly by the protocol implementation and the keys correspond to the validator roles of the nodes. In Eudico, these would be the keys that define the libp2p identities of nodes.

Given that in Eudico, the mempool already only contains Eudico messages that are ready to be ordered and their signatures do not need to be verified by the ordering layer, the VerifyClientSig function of the crypto module is not required and can be removed from the module.

Question

What key will we use for signing consensus protocol messages?

Answer

Ideally we should use the key that corresponds to the identity of the validator node as defined in the validator set.
In other words, whatever is used in whatever representation of the validator set to identify a validator, it must be (explicitly or implicitly) linked to a key pair such that

  1. the validator can use the private part to sign protocol messages and
  2. other validators can use the public part for verifying those messages.

Conclusion

Options

We have two options for implementing the crypto module for Eudico

  1. Use the libp2p-based identity of nodes and sign/verify protocol messages using the associated key pair. While this is the cleanest solution, it might have a practical caveat that the libp2p key (or an interface for signing arbitrary data with it) might not be easily accessible to the Mir implementation.

  2. Use the libp2p-based identity of nodes only to identify them on the network and explicitly associate a wallet key/address with this identity in the membership configuration.

How to proceed

Look for possibilities of signing arbitrary data using the libp2p key, but without spending much time on it (few hours max). On success, use option 1. On failure, use option 2.

Copy link
Contributor

@matejpavlovic matejpavlovic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.
I'll adapt the Mir crypto interface so we can simplify even further.

chain/consensus/mir/crypto.go Outdated Show resolved Hide resolved
Copy link
Contributor

@matejpavlovic matejpavlovic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gooks good in general, only minor comments, the most important one being the usage of the new crypto module.

We'll need to see about including the request payload, but that's for another PR.

chain/consensus/mir/crypto.go Outdated Show resolved Hide resolved
chain/consensus/mir/crypto.go Outdated Show resolved Hide resolved
chain/consensus/mir/manager.go Outdated Show resolved Hide resolved

go func() {
select {
case <-ctx.Done():
log.Debugf("Mir manager: context closed")
log.Infof("Mir manager %s: context closed", m.MirID)
m.Stop()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the manager supposed to stop only when the context given to it from outside is canceled, or should it also stop when the Mir node stops by itself for some reason (e.g. due to an error)?
Currently, if the Mir node encounters an error, the Manager is not stopped.
Moreover, if the Mir node stops by itself without an error, this whole goroutine will keep running until the external context is canceled.
Is that intended?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Case 1. If the Mir node encounters an error then we send the error to errChan and call managerCancel() that will stop the manager as a goroutine but it will not call the Stop function. Stop doesn't stop the manager it stops the Mir node. The question: if the Mir node has encountered an error does make sense to stop its components gracefully?
  2. Case 2. Mir node stops by itself without an error. According to the comments it Stops and returns when ctx is canceled. So it can't just finish all work and stop. Right? It stops via context only and then the special error is returned.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then I don't quite understand it... In the code it looks like m is the Manager and the code calls m.Stop(). Doesn't that stop the Manager?

Copy link
Contributor

@matejpavlovic matejpavlovic Jun 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the Mir node has encountered an error does make sense to stop its components gracefully?

Yes. The Mir Node does not really have a reason (or even a way) of stopping other modules like the WAL or Net on error. So in fact, they still need to be stopped from the outside event if the Node fails. In a way, the modules can be seen as components of the Node, but one can also see them as independent components that only interact using the node (after all they are also started separately from the Node). So it make sense to also stop them (preferably gracefully) separately from the Node (even if it fails).

It also happens to simplify the code to something like this:

func (m *Manager) Start(ctx context.Context) chan error {
	log.Infof("Mir manager %s starting", m.MirID)

	errChan := make(chan error, 1)

	go func() {
		
		// Run Mir node until it stops.
		if err := m.MirNode.Run(ctx); err != nil && !errors.Is(err, mir.ErrStopped) {
			log.Infof("Mir manager %s: Mir node stopped with error: %v", m.MirID, err)
			errChan <- err
		} else {
			log.Infof("Mir manager %s: Mir node stopped gracefully", m.MirID)
			errChan <- nil
		}
		
		// Perform cleanup of Node's modules.
		m.Stop()
	}()

	return errChan
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

chain/consensus/mir/manager.go Outdated Show resolved Hide resolved
chain/consensus/mir/mine.go Outdated Show resolved Hide resolved
@dnkolegov
Copy link
Collaborator Author

dnkolegov commented Jun 21, 2022 via email

@codecov-commenter
Copy link

Codecov Report

Merging #208 (4bc0ca7) into eudico (bb52565) will increase coverage by 1.29%.
The diff coverage is 69.07%.

Impacted file tree graph

@@            Coverage Diff             @@
##           eudico     #208      +/-   ##
==========================================
+ Coverage   21.26%   22.56%   +1.29%     
==========================================
  Files         597      609      +12     
  Lines       65858    66119     +261     
==========================================
+ Hits        14006    14919     +913     
+ Misses      49246    48516     -730     
- Partials     2606     2684      +78     
Impacted Files Coverage Δ
chain/consensus/mir/mine.go 67.85% <53.33%> (-7.15%) ⬇️
chain/consensus/mir/app.go 67.56% <66.66%> (-10.22%) ⬇️
chain/consensus/mir/manager.go 71.51% <68.75%> (-2.76%) ⬇️
chain/consensus/mir/crypto.go 75.00% <75.00%> (ø)
itests/kit/tools_eudico.go 55.81% <87.50%> (+2.09%) ⬆️
chain/consensus/mir/request_pool.go 100.00% <100.00%> (ø)
chain/consensus/mir/types.go 100.00% <100.00%> (ø)
chain/actors/aerrors/error.go 21.73% <0.00%> (-56.53%) ⬇️
chain/actors/aerrors/wrap.go 0.00% <0.00%> (-4.24%) ⬇️
...in/consensus/hierarchical/subnet/manager/subnet.go 51.18% <0.00%> (-3.15%) ⬇️
... and 44 more

@dnkolegov dnkolegov merged commit 4d729db into eudico Jun 21, 2022
@dnkolegov dnkolegov deleted the mir-crypto branch June 21, 2022 14:02
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants