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

Use new node contract in registry #107

Merged
merged 1 commit into from
Aug 13, 2024

Conversation

neekolas
Copy link
Contributor

@neekolas neekolas commented Aug 11, 2024

tl;dr

  • Creates new SmartContractRegistry that polls the smart contract to get the latest state of the nodes
  • Refactored the config out of the server to avoid circular dependencies and allow config objects to be passed in to other modules
  • Added a dev/run command that populates all the environment variables required
  • Created a notifier struct to power the SmartContractRegistry and publish changes to subscriptions

Why not use the indexer?

We could get the same result from indexing the chain based on events. This seemed more straightforward. We don't care about historical state here, so processing old events is just going to create noise and complexity. When any node starts up it just needs a full picture of all the other nodes right now. We also don't have tight latency requirements: this contract moves in the cadence of days or weeks.

Since we know the node list is going to be small forever, and this data is going to be frequently accessed, having it all live in memory is also way more performant.

Copy link
Contributor Author

neekolas commented Aug 11, 2024

@neekolas neekolas marked this pull request as ready for review August 11, 2024 15:02
@neekolas neekolas force-pushed the 08-10-use_new_node_contract_in_registry branch 6 times, most recently from 31e878e to 47898c7 Compare August 11, 2024 16:12
@neekolas neekolas force-pushed the 08-10-use_new_node_contract_in_registry branch from d79e5fb to 2e139d8 Compare August 12, 2024 21:40
@neekolas neekolas force-pushed the 08-10-use_new_node_contract_in_registry branch 3 times, most recently from 1afaced to 601c7c1 Compare August 12, 2024 22:24
@neekolas neekolas mentioned this pull request Aug 12, 2024
@neekolas neekolas force-pushed the 08-10-use_new_node_contract_in_registry branch from 601c7c1 to 9bb66a2 Compare August 12, 2024 22:59
@@ -8,9 +8,9 @@

`xmtpd` (XMTP daemon) is an experimental version of XMTP node software. It is **not** the node software that currently forms the XMTP network.

After `xmtpd` meets specific functional requirements, the plan is for it to become the node software that powers the XMTP network.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Think my editor has a default Markdown formatter. We can make that standard issue in the repo so we don't get diffs like this.

@neekolas neekolas force-pushed the 08-10-use_new_node_contract_in_registry branch 2 times, most recently from 893cbec to 59a23af Compare August 12, 2024 23:58
@neekolas neekolas changed the base branch from 08-10-update_node_contract to graphite-base/107 August 13, 2024 00:32
@neekolas neekolas force-pushed the 08-10-use_new_node_contract_in_registry branch from 59a23af to e2d7da7 Compare August 13, 2024 00:32
@neekolas neekolas changed the base branch from graphite-base/107 to main August 13, 2024 00:33
require.Equal(t, 100, getCurrentCount())
}

func countChannel[Kind any](ch <-chan Kind) func() int {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was to prevent go's race detection from getting mad about data races in our tests

@@ -72,5 +74,5 @@ func (s *ReplicationServer) Shutdown() {
}

func parsePrivateKey(privateKeyString string) (*ecdsa.PrivateKey, error) {
return crypto.HexToECDSA(privateKeyString)
return crypto.HexToECDSA(strings.TrimPrefix(privateKeyString, "0x"))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Lets us re-use the PK environment variable we are using with forge to deploy the contract locally, which expects a 0x prefix. HexToECDSA does not expect the 0x


if ! which forge &>/dev/null; then curl -L https://foundry.paradigm.xyz | bash ; fi
if ! which migrate &>/dev/null; then brew install golang-migrate; fi
if ! which golangci-lint &>/dev/null; then brew install golangci-lint; fi
if ! which shellcheck &>/dev/null; then brew install shellcheck; fi
if ! which mockery &>/dev/null; then brew install mockery; fi
if ! which mockery &>/dev/null; then go install github.com/vektra/mockery/v2; fi
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because the tools.go file puts this in our go.mod, we can now get a deterministic version for the dependency when we do a Go install.

Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be simpler to just specify the version in the install command here, rather than updating the tools.go file?

Copy link
Contributor

@richardhuaaa richardhuaaa left a comment

Choose a reason for hiding this comment

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

This looks really hard to get right, well done

Comment on lines +5 to +6
export CHAIN_RPC_URL=$DOCKER_RPC_URL # From contracts/.env
export NODE_PRIVATE_KEY=$PRIVATE_KEY # From contracts/.env
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason that dev/local.env and contracts/.env are not consolidated into a single file? For example, is the PRIVATE_KEY used anywhere else?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We use the stuff in contracts/local.env to deploy the smart contract locally. Could consolidate, but I'd like to figure out just how complicated all the local smart contract dev stuff is going to be with a full set of contracts and a more sophisticated deployer. My guess is that we're going to have a lot more configuration that is specific to the contracts.

Comment on lines +157 to +163
s.newNodesNotifier.trigger(nodes)

s.nodesMutex.Lock()
defer s.nodesMutex.Unlock()
for _, node := range nodes {
s.nodes[node.NodeId] = node
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you walk through what happens in the scenario when a listener is notified of a new node, but the registry hasn't written that node into its map yet? (e.g. the listener calls GetNodes() first)

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 wouldn't expect the listener to need to do that (they already have all the new nodes). But maybe I should move the trigger call to be after just to be safe.


if ! which forge &>/dev/null; then curl -L https://foundry.paradigm.xyz | bash ; fi
if ! which migrate &>/dev/null; then brew install golang-migrate; fi
if ! which golangci-lint &>/dev/null; then brew install golangci-lint; fi
if ! which shellcheck &>/dev/null; then brew install shellcheck; fi
if ! which mockery &>/dev/null; then brew install mockery; fi
if ! which mockery &>/dev/null; then go install github.com/vektra/mockery/v2; fi
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be simpler to just specify the version in the install command here, rather than updating the tools.go file?

// Unmarshal the signing key.
// If invalid, mark the config as being invalid as well. Clients should treat the
// node as unhealthy in this case
signingKey, err := crypto.UnmarshalPubkey(rawNode.Node.SigningKeyPub)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should loudly surface an error instead of quietly excluding the node.

It's not expected for an invalid key to be written to the registry, and failing to read it here would imply some inconsistency in how the key is interpreted.

This would also be an argument for why we shouldn't let node operators change the http address themselves. It might be simpler for the DAO to do all validation before writing to the registry (or having the smart contract do the validation) so that everything in the registry can be treated as correct downstream.

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 can update it to at least log something loudly.

But I do think we need to treat the inputs in the smart contract as somewhat untrusted. Hopefully we'll pre-validate and this will never happen, but that's a human-driven manual process.

Comment on lines +9 to +10
changedNodeNotifiers map[uint16]*notifier[Node]
changedNodeNotifiersMutex sync.Mutex
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think these notifiers ever get triggered?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This whole thing is getting deleted pretty soon

Copy link
Contributor Author

neekolas commented Aug 13, 2024

Merge activity

  • Aug 13, 1:59 PM PDT: @neekolas started a stack merge that includes this pull request via Graphite.
  • Aug 13, 2:00 PM PDT: @neekolas merged this pull request with Graphite.

@neekolas neekolas merged commit 4621c3e into main Aug 13, 2024
9 checks passed
@neekolas neekolas deleted the 08-10-use_new_node_contract_in_registry branch August 13, 2024 21:00
@neekolas
Copy link
Contributor Author

neekolas commented Aug 13, 2024

@richardhuaaa

Would it be simpler to just specify the version in the install command here, rather than updating the tools.go file?

IDK. Having it all live in the go.mod does make upgrades nicer than having to edit some random script that's easy to be forgotten about. But I don't love either solution.

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.

2 participants