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

throw an error if the registry contract hasn't been deployed #22

Merged
merged 5 commits into from
Aug 28, 2023

Conversation

joewagner
Copy link
Contributor

@joewagner joewagner commented Aug 24, 2023

Overview

As an improvement working toward fixing #40 this PR introduces behavior that check if the registry has been deployed before starting the Validator. If the contract is not deployed an error is thrown. This will make CI tests fail immediately and obviously, which will make the reason for failure more obvious.

Details

Along with requiring the existence of the registry on chain for successful startup, there are a few other changes:

  • This reverts some of the port failure retry logic since that didn't solve the issue with CI failures.
  • This moves the startup and shutdown tests into their own test file
  • This moves the hard coded registry contract address up one level, from the validator.ts file to the main.ts file. I needed to do this to enable checking the existence of the deployed contract. This also moves one step closer to getting the contract out of the deploy, which isn't possible atm since the deploy fails silently.

NOTE: this is based off the publish branch. Once that's merged this will be pointed at main.

@joewagner joewagner changed the base branch from main to publish August 24, 2023 20:13
@joewagner joewagner marked this pull request as ready for review August 24, 2023 20:41
waitForReady,
} from "./util.js";

const spawnSync = spawn.sync;

// TODO: maybe this can be parsed out of the deploy process?
// Since it's always the same address just hardcoding for now.
const registryAddress = "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512";
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 used to reside in the validator.ts file, but we need access to it here now so it's been moved. If we can find a way to get this value from the deploy process, that would be ideal. Until then this works.

Copy link
Member

Choose a reason for hiding this comment

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

We can't just get this from the underlying client package?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

by the client you mean @tableland/evm?

@@ -62,7 +67,7 @@ class LocalTableland {
typeof config.registryDir === "string" &&
config.registryDir.trim() !== ""
) {
this.registryDir = config.registryDir;
this.registryDir = config.registryDir.trim();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

trimming before setting the instance value, which means all later access doesn't need to trim

@@ -80,19 +85,15 @@ class LocalTableland {
}

async #_start(config: Config = {}): Promise<void> {
if (
typeof this.registryDir !== "string" ||
this.registryDir.trim() === ""
Copy link
Contributor Author

Choose a reason for hiding this comment

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

See above... This has already been trimmed.

this.#_cleanup();

// Check if the hardhat port is in use (defaults to 5 retries, 300ms b/w each try)
const registryPortIsTaken = await probePortInUse(this.registryPort);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

An old PR attempted to fix the CI issues by retrying the same hardhat node port in hopes it will become available. The issue comes from a crashing contract deploy process, not a failure to start the hardhat node. We no longer need this retry logic. I've left the logic that ensures the port is available, since this is a nice mechanism to fail fast and loud if the port was already taken.

@@ -101,14 +102,18 @@ class LocalTableland {
// Else, notify the user only if it's a not the default and is custom.
if (registryPortIsTaken) {
throw new Error(`port ${this.registryPort} already in use`);
} 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.

Some cleanup here. We don't need an else clause because throwing breaks out of this function.

this.registryPort
}`
);
this.silent !== true
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 getting logged even if the dev had set silent: true


const deployed = await this.#_ensureRegistry();
if (!deployed) {
throw new Error(
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 ensures we fail fast and loud if the deploy failed. At the moment you have to look through the CI logs and see if the failing tests are becaseue the registry wasn't deployed, or for some legitimate reason.

const code = await provider.getCode(registryAddress);

// if the contract exists, and is not empty, code will not be equal to 0x
return code !== "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.

To check if the registry was deployed, we can use the ethers.js getCode method. If the contract exists it will have a long string corresponding to the contract code. If not it will equal "0x".

Copy link
Member

Choose a reason for hiding this comment

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

Smart

@@ -1,220 +1,17 @@
import { type Server } from "node:net";
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The changes in this file are the result of moving the network startup and shutdown tests to their own file.

test("fails to start due to registry deploy failure", async function () {
const lt = new LocalTableland({ silent: true });
// note: need to cast as `any` since the method is private
const deployStub = stub(lt, "_deployRegistry" as any);
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 created a noop stub so the registry isn't deployed. This must result in an error instead of successful startup.

All the other tests in this file were moved from the e2e file.

carsonfarmer
carsonfarmer previously approved these changes Aug 25, 2023
Copy link
Member

@carsonfarmer carsonfarmer left a comment

Choose a reason for hiding this comment

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

Really nice work here @joewagner!

waitForReady,
} from "./util.js";

const spawnSync = spawn.sync;

// TODO: maybe this can be parsed out of the deploy process?
// Since it's always the same address just hardcoding for now.
const registryAddress = "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512";
Copy link
Member

Choose a reason for hiding this comment

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

We can't just get this from the underlying client package?

@@ -220,6 +222,33 @@ class LocalTableland {
console.log("\n\n*************************************\n");
}

// note: Tests are using sinon to stub this method. Because typescript compiles ecmascript
// private features, i.e. hash syntax, in a way that does not work with sinon we must
Copy link
Member

Choose a reason for hiding this comment

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

Wait, really? Huh, there are apparently other libs that have a problem with this. Do you have a reference for the issue? Just for interest sake?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great question, I couldn't find an issue in Sinon. Maybe I should open one? Here's the Sinon source https://github.com/sinonjs/sinon/blob/main/lib/sinon/util/core/is-non-existent-property.js#L10
When you have a class the uses the js private class feature, you'll always get false when you do something like:

class Derp {
  #_foo() {
    return "foo";
  }
}

const instance = new Derp();

console.log("#_foo" in instance); // => false
console.log(instance.#_foo); // => type error

Maybe it's impossible to spy on private fields?

const code = await provider.getCode(registryAddress);

// if the contract exists, and is not empty, code will not be equal to 0x
return code !== "0x";
Copy link
Member

Choose a reason for hiding this comment

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

Smart

Base automatically changed from publish to main August 25, 2023 18:49
@joewagner joewagner dismissed carsonfarmer’s stale review August 25, 2023 18:49

The base branch was changed.

@joewagner
Copy link
Contributor Author

joewagner commented Aug 25, 2023

@carsonfarmer This was automatically changed to point at main after merging tablelandnetwork/local-tableland#21, can you give another ✅ ?

[EDIT]: almost forgot to bump the patch version, gtg now.

@joewagner
Copy link
Contributor Author

@asutula I added the fix for the SDK regression here since without the changes in this PR the CI fails constantly.
Can you give a 👍 to this?

@joewagner joewagner merged commit 04cdf8a into main Aug 28, 2023
4 checks passed
@joewagner joewagner deleted the joe/fix-ci branch August 28, 2023 17:08
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.

3 participants