Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support EIP1271 signatures #32

Merged
merged 5 commits into from
Oct 25, 2024

Conversation

adamgall
Copy link
Contributor

@adamgall adamgall commented Oct 14, 2024

Work In Progress

Closes #31

This hasn't been tested or even executed yet. But it does build! Open to feedback as I continue implementation and testing.

Notes

This PR will make the implementation of #26 less straightforward than originally expected.

api/router.go Outdated Show resolved Hide resolved
api/router.go Outdated Show resolved Hide resolved
api/router.go Outdated Show resolved Hide resolved
services/credentials.go Outdated Show resolved Hide resolved
services/credentials.go Outdated Show resolved Hide resolved
api/router.go Outdated Show resolved Hide resolved
external/rescue_proxy.go Show resolved Hide resolved
services/service.go Outdated Show resolved Hide resolved
nodeID, err := s.getNodeID(msg, sig)
if 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.

can we change this to an if/else so that we can deduplicate the two calls to s.checkNodeAuthorization?

Copy link
Contributor Author

@adamgall adamgall Oct 23, 2024

Choose a reason for hiding this comment

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

Hmm, I don't think I follow how to make that happen.

The call to getNodeID(msg, sig) will not give an error if the signature was made with a contract, it will just recover a random incorrect address. We do need to call checkNodeAuthorization with that address to see if it is actually in the "whitelist".

The second call to checkNodeAuthorization below checks the eip1271 recovered address for it's inclusion on the whitelist.

I'm not sure how we would avoid making two calls to checkNodeAuthorization in the case that the signature was generated via eip1271.

If I'm missing the point of your request, please keep poking me in the right direction :)

Copy link
Contributor

Choose a reason for hiding this comment

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

hmm yeah maybe not if/else, but

if err != nil {
  // Attempt EIP-1271 validation
  ...
  valid, err := ...
  if err != nil {
    // return error
  }
}
 // checkNodeAuthz using either the EOA address or SC address

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But how would we know to check with either the EOA address or the SC address? We need to check with both. Either neither of them will pass checkNodeAuthz, or one of them will pass checkNodeAuth. AFAIK it's not possible to know which one is "valid" until we do the actual check.

Copy link
Contributor

Choose a reason for hiding this comment

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

As mentioned offline- checking the EOA sig needs to return an error if the recovered address doesn't match the one in the json payload. I think it's possible for getNodeID to return a valid address for an EIP1271 signature, just essentially random bytes.

Once we have that validation, we know a priori whether an EOA signed the message, and we can implement this as a more "pure" bit of fallback logic (ie, first check EOA signature, if not valid, check EIP1271, and use the appropriate address in a single checkNodeAuthorization call.)

Copy link
Contributor

Choose a reason for hiding this comment

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

Will close #26

@adamgall adamgall marked this pull request as ready for review October 23, 2024 02:28
api/messages.go Show resolved Hide resolved
api/router.go Outdated
zap.String("sig", out.Sig),
zap.String("address", out.Address.Hex()),
zap.String("msg", string(out.Msg)),
zap.String("sig", string(out.Sig)),
Copy link
Contributor

Choose a reason for hiding this comment

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

out.sig is a []byte that represents binary, so we need to hex-encode before logging.

Msg is expected to be valid ascii, so the cast is fine there.

api/router.go Show resolved Hide resolved
external/rescue_proxy.go Show resolved Hide resolved
nodeID, err := s.getNodeID(msg, sig)
if 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.

As mentioned offline- checking the EOA sig needs to return an error if the recovered address doesn't match the one in the json payload. I think it's possible for getNodeID to return a valid address for an EIP1271 signature, just essentially random bytes.

Once we have that validation, we know a priori whether an EOA signed the message, and we can implement this as a more "pure" bit of fallback logic (ie, first check EOA signature, if not valid, check EIP1271, and use the appropriate address in a single checkNodeAuthorization call.)

nodeID, err := s.getNodeID(msg, sig)
if 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.

Will close #26

@adamgall adamgall force-pushed the support-eip1271-signatures branch 2 times, most recently from 4114853 to 6d6593f Compare October 24, 2024 19:08
@adamgall adamgall force-pushed the support-eip1271-signatures branch from 6d6593f to 6d75c5a Compare October 24, 2024 19:19
@adamgall
Copy link
Contributor Author

Alright @jshufro! Ready for another round of review :)

Copy link
Contributor

@jshufro jshufro left a comment

Choose a reason for hiding this comment

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

one small bug and it's good to go

api/messages.go Outdated
c.Msg = []byte(aux.Msg)

// Convert Sig
c.Sig = []byte(aux.Sig)
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated and pushed

api/router.go Outdated
zap.String("sig", out.Sig),
zap.String("address", out.Address.Hex()),
zap.String("msg", string(out.Msg)),
zap.String("sig", hex.EncodeToString(out.Sig)),
Copy link
Contributor

Choose a reason for hiding this comment

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

since we're gonna use the function from my previous comment, use https://pkg.go.dev/github.com/ethereum/[email protected]/common/hexutil#Encode here to restore the 0x prefix

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated and pushed

@jshufro
Copy link
Contributor

jshufro commented Oct 25, 2024

Seems like the grpc lint errors are from the dependency bump, so it falls on you to see about fixing them

@adamgall
Copy link
Contributor Author

Seems like the grpc lint errors are from the dependency bump, so it falls on you to see about fixing them

Ok, I'll look into this. I wasn't aware that there were grpc lint errors! Thanks for your patience as I make my way into golang development 😅

@jshufro jshufro merged commit e45e0fa into Rocket-Rescue-Node:main Oct 25, 2024
2 of 3 checks passed
@adamgall adamgall deleted the support-eip1271-signatures branch October 26, 2024 00:37
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.

Support EIP-1271 signatures in both operator_info and credentials endpoints
2 participants