-
Notifications
You must be signed in to change notification settings - Fork 7
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
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
31e878e
to
47898c7
Compare
31b5549
to
5d7b02f
Compare
d79e5fb
to
2e139d8
Compare
5d7b02f
to
0efeea1
Compare
1afaced
to
601c7c1
Compare
0efeea1
to
894e74b
Compare
601c7c1
to
9bb66a2
Compare
@@ -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. |
There was a problem hiding this comment.
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.
893cbec
to
59a23af
Compare
59a23af
to
e2d7da7
Compare
require.Equal(t, 100, getCurrentCount()) | ||
} | ||
|
||
func countChannel[Kind any](ch <-chan Kind) func() int { |
There was a problem hiding this comment.
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")) |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this 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
export CHAIN_RPC_URL=$DOCKER_RPC_URL # From contracts/.env | ||
export NODE_PRIVATE_KEY=$PRIVATE_KEY # From contracts/.env |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
s.newNodesNotifier.trigger(nodes) | ||
|
||
s.nodesMutex.Lock() | ||
defer s.nodesMutex.Unlock() | ||
for _, node := range nodes { | ||
s.nodes[node.NodeId] = node | ||
} |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
changedNodeNotifiers map[uint16]*notifier[Node] | ||
changedNodeNotifiersMutex sync.Mutex |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
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. |
tl;dr
SmartContractRegistry
that polls the smart contract to get the latest state of the nodesserver
to avoid circular dependencies and allow config objects to be passed in to other modulesdev/run
command that populates all the environment variables requirednotifier
struct to power theSmartContractRegistry
and publish changes to subscriptionsWhy 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.