Skip to content

WIP: Priv Validator Refactor#1044

Closed
ebuchman wants to merge 10 commits intodevelopfrom
priv_val
Closed

WIP: Priv Validator Refactor#1044
ebuchman wants to merge 10 commits intodevelopfrom
priv_val

Conversation

@ebuchman
Copy link
Contributor

@ebuchman ebuchman commented Dec 31, 2017

#673

Hard to see the changes because I busted up the file into its own package, but it should be much easier to read through now.

@silasdavis @wrl @ethanfrey @adrianbrink @melekes

@ebuchman ebuchman requested a review from melekes as a code owner December 31, 2017 02:59
@adrianbrink
Copy link
Contributor

This cleans it up a lot. :-)

What is the purpose of PrivValidatorStore? Also, shouldn't CarefulSigner be rather a struct that implements PrivValidator?

Couldn't we remove the Signer interface and just let the client implement PrivValidator. This would mean that we'd have a NanoPrivValidator struct.

I am wondering though how it would work with moving the signing logic into a Thales HSM.

@adrianbrink
Copy link
Contributor

I'm wary though how people would use different signers. Ideally wanting to use a NanoLedger or Thales shouldn't require you to fork Tendermint Core. Either we have a finite list of supported signers hardcoded in Core and then try to figure out which one to use through a config option or Core expects a signer to be available behind some socket so that way in the config you can specify a socket address and Tendermint Core will just send the bytes to sign that way.

@silasdavis
Copy link
Contributor

I'm wary though how people would use different signers.
@adrianbrink what are you wary about in particular? Note that we can pass in a PrivValidator so we wouldn't need fork Tendermint core to pass in an alternative signer. Nothing to stop you providing configurable default signers, but the flexibility to provide a signer is useful.

I'm not quite following the full idea with CarefulSigner, but I don't see any implementation of GetCarefulSigner so assume that is coming.

@ebuchman
Copy link
Contributor Author

What is the purpose of PrivValidatorStore

A place to store the actual priv key, so eg. it can be encrypted on disk. This might go away though.

Also, shouldn't CarefulSigner be rather a struct that implements PrivValidator
I'm not quite following the full idea with CarefulSigner

CarefulSigner is the thing that prevents double signing. In this issue, Silas mentioned a Verifier interface - that's what this is. It decouples signing from the verification. For instance, you could use a ledger for just the signing, but still use our LastSignedInfo to prevent double signing. Or you could use the ledger to implement both.

Couldn't we remove the Signer interface and just let the client implement PrivValidator

Possibly, but at least for now that would spoil CarefulSigner

I am wondering though how it would work with moving the signing logic into a Thales HSM.

The HSM would implement Signer and CarefulSigner

Either we have a finite list of supported signers hardcoded in Core and then try to figure out which one to use through a config option or Core expects a signer to be available behind some socket so that way in the config you can specify a socket address and Tendermint Core will just send the bytes to sign that way.

Both of these sounds pretty good. Let's start with a list of supported things (unencrypted, encrypted, ledger, thales) and then open it up to a socket.

power := v.Power
if power < 0 {
return fmt.Errorf("Power (%d) overflows int64", v.Power)
return fmt.Errorf("Power (%d) must be positive int64", v.Power)
Copy link
Contributor

Choose a reason for hiding this comment

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

v.Power -> power

// or else generates a new one and saves it to the filePath.
func LoadOrGenDefaultPrivValidator(filePath string, store PrivValidatorStore) *DefaultPrivValidator {
var pv *DefaultPrivValidator
if _, err := os.Stat(filePath); err == nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

cmn.FileExists

privVal.Save()
addr := privVal.GetAddress()
privVal.CarefulSigner.(*LastSignedInfo).LastHeight = height
privVal.CarefulSigner.(*LastSignedInfo).saveFn(privVal.CarefulSigner)
Copy link
Contributor

Choose a reason for hiding this comment

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

this is harder to read&understand comparing to privVal.Save()


//-----------------------------------------------------------------

// DefaultSigner implements Signer.
Copy link
Contributor

Choose a reason for hiding this comment

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

how about a check: var _ Signer = (*DefaultSigner)(nil)

return stepPrecommit
default:
cmn.PanicSanity("Unknown vote type")
return 0
Copy link
Contributor

Choose a reason for hiding this comment

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

unreachable code

return val, privVal
}

type Signer interface {
Copy link
Contributor

Choose a reason for hiding this comment

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

2 Signer interfaces. Wont this be confusing?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes this one is just for testing tho. problem of circular imports ...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll change it to TestSigner

@adrianbrink
Copy link
Contributor

How about calling it Verifier instead of CarefulSigner. I have a commit with these changes but you are committing faster than me :-) @ebuchman

@ebuchman
Copy link
Contributor Author

ebuchman commented Dec 31, 2017

It's not just a Verifier though - at the least its a VerifyAndSigner. And it's also something that's expected to have mutable internal state if its going to keep track of things to not double sign. So it seemed CarefulSigner was a good fit for a name.

The CarefulSigner interface isn't actually being used in any useful way right now, but I think it's useful to have, especially for cases where the LastSignedInfo is on disk but the Signer is an HSM.

The goal is for the DefaultPrivValidator to just use Signer and CarefulSigner interfaces directly, but we need to be able to unmarshall into those, so I'm waiting on changes to go-wire to make that work nicely. In the meantime, it should be a very small amount of code to add a new priv validator - the only thing is you have to handle your own marshal/unmarshal for saving/loading from disk. Once the new wire changes are in, everyone can just use the DefaultPrivValidator, and provide the Signer and CarefulSigner they like :)

@codecov-io
Copy link

codecov-io commented Dec 31, 2017

Codecov Report

Merging #1044 into develop will decrease coverage by 0.13%.
The diff coverage is 59.04%.

@@             Coverage Diff             @@
##           develop    #1044      +/-   ##
===========================================
- Coverage    59.66%   59.52%   -0.14%     
===========================================
  Files          116      119       +3     
  Lines        10667    10772     +105     
===========================================
+ Hits          6364     6412      +48     
- Misses        3725     3779      +54     
- Partials       578      581       +3

@ebuchman
Copy link
Contributor Author

ebuchman commented Jan 5, 2018

Ok - I went through this again and simplified.

Please take a look at the ADR and the new simplified code.

Dropped the CarefulSigner and just put those methods on the LastSignedInfo.

Shouldn't be any lost functionality really.

Tendermint will jsut support PrivValidatorUnencrypted and PrivValidatorSocket.

Folks will still be able to override in-process if they want with their own PrivValidator, and should be able to easily use the LastSignedInfo.

@ebuchman ebuchman mentioned this pull request Jan 5, 2018
power := v.Power
if power < 0 {
return fmt.Errorf("Power (%d) overflows int64", v.Power)
return fmt.Errorf("Power (%d) must be positive int64", power)
Copy link
Contributor

Choose a reason for hiding this comment

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

let's add address here too: "Power (%d) of validator %X must be positive int64", power, address

vote1 := makeVote(val, chainID, 0, 10, 2, 1, blockID)
badVote := makeVote(val, chainID, 0, 10, 2, 1, blockID)
badVote.Signature = val2.PrivKey.Sign(SignBytes(chainID, badVote))
badVote.Signature, _ = val2.Sign(SignBytes(chainID, badVote))
Copy link
Contributor

Choose a reason for hiding this comment

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

it's better not ignore errors. why not do require.NoError(t, err)

"github.com/tendermint/tendermint/types"
)

// TODO: type ?
Copy link
Contributor

Choose a reason for hiding this comment

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

step is exposed in LastSignedInfo, so don't think this is a good idea because of that


// TODO: type ?
const (
stepNone int8 = 0 // Used to distinguish the initial state
Copy link
Contributor

Choose a reason for hiding this comment

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

iota

func (info *LastSignedInfo) Reset() {
info.Height = 0
info.Round = 0
info.Step = 0
Copy link
Contributor

Choose a reason for hiding this comment

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

stepNone

@ebuchman
Copy link
Contributor Author

ebuchman commented Feb 9, 2018

Closing in favor of fresh new PR without the integrations #1203

@ebuchman ebuchman closed this Feb 9, 2018
@xla xla deleted the priv_val branch September 18, 2018 20:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants