diff --git a/Cargo.lock b/Cargo.lock index 34b9005a5..0dfa87339 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4968,6 +4968,7 @@ dependencies = [ "smallvec", "sqlx", "static_assertions", + "stratus_macros", "strum", "sugars", "tempfile", @@ -4987,6 +4988,15 @@ dependencies = [ "vergen", ] +[[package]] +name = "stratus_macros" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.76", +] + [[package]] name = "stringprep" version = "0.1.4" diff --git a/Cargo.toml b/Cargo.toml index ff9c8a831..5f480cf46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ quick_cache = "=0.6.9" sugars = "=3.0.1" thiserror = "=1.0.61" uuid = { version = "=1.10.0", features = ["v7"]} +stratus_macros = { path = "./crates/stratus_macros" } # async tokio = { version = "=1.38.0", features = [ diff --git a/crates/stratus_macros/src/lib.rs b/crates/stratus_macros/src/lib.rs index 38f7e443c..180ac3667 100644 --- a/crates/stratus_macros/src/lib.rs +++ b/crates/stratus_macros/src/lib.rs @@ -1,6 +1,13 @@ use proc_macro::TokenStream; use quote::quote; -use syn::{parse_macro_input, DeriveInput, Data, Fields, Meta, Expr, ExprLit, Lit}; +use syn::parse_macro_input; +use syn::Data; +use syn::DeriveInput; +use syn::Expr; +use syn::ExprLit; +use syn::Fields; +use syn::Lit; +use syn::Meta; #[proc_macro_derive(ErrorCode, attributes(error_code))] pub fn derive_error_code(input: TokenStream) -> TokenStream { @@ -87,10 +94,11 @@ fn derive_error_code_impl(input: DeriveInput) -> proc_macro2::TokenStream { #[cfg(test)] mod tests { - use crate::derive_error_code_impl; use proc_macro2::TokenStream; use quote::quote; + use crate::derive_error_code_impl; + #[test] fn test_derive_error_code() { let input = TokenStream::from(quote! { diff --git a/e2e/cloudwalk-contracts/integration/test/leader-follower-change.test.ts b/e2e/cloudwalk-contracts/integration/test/leader-follower-change.test.ts index e556e5897..2d3d7a7a2 100644 --- a/e2e/cloudwalk-contracts/integration/test/leader-follower-change.test.ts +++ b/e2e/cloudwalk-contracts/integration/test/leader-follower-change.test.ts @@ -49,7 +49,7 @@ describe("Leader & Follower change integration test", function () { "2s", "100ms", ]); - expect(response.data.error.code).to.equal(-32009); + expect(response.data.error.code).to.equal(7007); expect(response.data.error.message).to.equal("Can't change miner mode while transactions are enabled."); }); @@ -62,7 +62,7 @@ describe("Leader & Follower change integration test", function () { "2s", "100ms", ]); - expect(response.data.error.code).to.equal(-32603); + expect(response.data.error.code).to.equal(6002); expect(response.data.error.message.split("\n")[0]).to.equal( "Unexpected error: can't change miner mode from Interval without pausing it first", ); @@ -103,7 +103,7 @@ describe("Leader & Follower change integration test", function () { it("Change Follower to Leader with transactions enabled should fail", async function () { updateProviderUrl("stratus-follower"); const response = await sendAndGetFullResponse("stratus_changeToLeader", []); - expect(response.data.error.code).to.equal(-32009); + expect(response.data.error.code).to.equal(7007); expect(response.data.error.message).to.equal("Can't change miner mode while transactions are enabled."); }); @@ -196,7 +196,7 @@ describe("Leader & Follower change integration test", function () { let successCount = 0; let semaphoreFailureCount = 0; - const SEMAPHORE_ERROR_CODE = -32009; + const SEMAPHORE_ERROR_CODE = 7005; const SEMAPHORE_ERROR_MESSAGE = "Stratus node is already in the process of changing mode."; allResponses.forEach((response, index) => { diff --git a/e2e/cloudwalk-contracts/integration/test/leader-follower-health.test.ts b/e2e/cloudwalk-contracts/integration/test/leader-follower-health.test.ts index 1020d404f..276d7c49a 100644 --- a/e2e/cloudwalk-contracts/integration/test/leader-follower-health.test.ts +++ b/e2e/cloudwalk-contracts/integration/test/leader-follower-health.test.ts @@ -12,7 +12,7 @@ it("Test follower health is based on getting new blocks", async function () { await new Promise((resolve) => setTimeout(resolve, 5000)); const unhealthyResponse = await sendAndGetFullResponse("stratus_health", []); - expect(unhealthyResponse.data.error.code).to.equal(-32009); + expect(unhealthyResponse.data.error.code).to.equal(7001); expect(unhealthyResponse.data.error.message).to.equal("Stratus is not ready to start servicing requests."); // Start the leader again diff --git a/e2e/cloudwalk-contracts/integration/test/leader-follower-importer.test.ts b/e2e/cloudwalk-contracts/integration/test/leader-follower-importer.test.ts index e67ecb6b7..e5d2f70fa 100644 --- a/e2e/cloudwalk-contracts/integration/test/leader-follower-importer.test.ts +++ b/e2e/cloudwalk-contracts/integration/test/leader-follower-importer.test.ts @@ -33,7 +33,7 @@ describe("Leader & Follower importer integration test", function () { it("Shutdown command to Leader should fail", async function () { updateProviderUrl("stratus"); const responseLeader = await sendAndGetFullResponse("stratus_shutdownImporter", []); - expect(responseLeader.data.error.code).eq(-32009); + expect(responseLeader.data.error.code).eq(7003); expect(responseLeader.data.error.message).eq("Stratus node is not a follower."); }); @@ -46,7 +46,7 @@ describe("Leader & Follower importer integration test", function () { it("Shutdown command to Follower when Importer is already shutdown should fail", async function () { updateProviderUrl("stratus-follower"); const responseFollower = await sendAndGetFullResponse("stratus_shutdownImporter", []); - expect(responseFollower.data.error.code).to.equal(-32603); + expect(responseFollower.data.error.code).to.equal(4002); expect(responseFollower.data.error.message).to.equal("Importer is already shutdown."); }); @@ -56,7 +56,7 @@ describe("Leader & Follower importer integration test", function () { expect(followerNode.is_leader).to.equal(false); expect(followerNode.is_importer_shutdown).to.equal(true); const followerHealth = await sendAndGetFullResponse("stratus_health", []); - expect(followerHealth.data.error.code).eq(-32009); + expect(followerHealth.data.error.code).eq(7001); expect(followerHealth.data.error.message).eq("Stratus is not ready to start servicing requests."); }); @@ -97,7 +97,7 @@ describe("Leader & Follower importer integration test", function () { const nonce = parseInt(nonceResponse.data.result, 16); const signedTx = await BOB.signWeiTransfer(ALICE.address, 1, nonce); const txResponse = await sendAndGetFullResponse("eth_sendRawTransaction", [signedTx]); - expect(txResponse.data.error.code).to.equal(-32603); + expect(txResponse.data.error.code).to.equal(5001); expect(txResponse.data.error.message).to.equal("Consensus is temporarily unavailable for follower node."); }); @@ -109,14 +109,14 @@ describe("Leader & Follower importer integration test", function () { "2s", "100ms", ]); - expect(responseLeader.data.error.code).to.equal(-32009); + expect(responseLeader.data.error.code).to.equal(7003); expect(responseLeader.data.error.message).to.equal("Stratus node is not a follower."); }); it("Init command to Follower without addresses should fail", async function () { updateProviderUrl("stratus-follower"); const responseInvalidFollower = await sendAndGetFullResponse("stratus_initImporter", []); - expect(responseInvalidFollower.data.error.code).to.equal(-32602); + expect(responseInvalidFollower.data.error.code).to.equal(1005); expect(responseInvalidFollower.data.error.message).to.equal("Expected String parameter, but received nothing."); }); @@ -127,7 +127,7 @@ describe("Leader & Follower importer integration test", function () { "2s", "100ms", ]); - expect(responseInvalidAddressFollower.data.error.code).to.equal(-32603); + expect(responseInvalidAddressFollower.data.error.code).to.equal(4004); expect(responseInvalidAddressFollower.data.error.message).to.equal("Failed to initialize importer."); }); @@ -148,7 +148,7 @@ describe("Leader & Follower importer integration test", function () { "2s", "100ms", ]); - expect(responseSecondInitFollower.data.error.code).to.equal(-32603); + expect(responseSecondInitFollower.data.error.code).to.equal(4001); expect(responseSecondInitFollower.data.error.message).to.equal("Importer is already running."); }); diff --git a/e2e/cloudwalk-contracts/integration/test/leader-follower-miner.test.ts b/e2e/cloudwalk-contracts/integration/test/leader-follower-miner.test.ts index 6e59346b3..32afbc255 100644 --- a/e2e/cloudwalk-contracts/integration/test/leader-follower-miner.test.ts +++ b/e2e/cloudwalk-contracts/integration/test/leader-follower-miner.test.ts @@ -35,14 +35,14 @@ describe("Miner mode change integration test", function () { it("Miner change to External on Leader should fail because transactions are enabled", async function () { updateProviderUrl("stratus"); const response = await sendAndGetFullResponse("stratus_changeMinerMode", ["external"]); - expect(response.data.error.code).eq(-32009); + expect(response.data.error.code).eq(7007); expect(response.data.error.message).eq("Can't change miner mode while transactions are enabled."); }); it("Miner change to Interval on Follower should fail because transactions are enabled", async function () { updateProviderUrl("stratus-follower"); const response = await sendAndGetFullResponse("stratus_changeMinerMode", ["1s"]); - expect(response.data.error.code).eq(-32009); + expect(response.data.error.code).eq(7007); expect(response.data.error.message).eq("Can't change miner mode while transactions are enabled."); }); @@ -65,7 +65,7 @@ describe("Miner mode change integration test", function () { it("Miner change to External on Leader should fail because miner is enabled", async function () { updateProviderUrl("stratus"); const response = await sendAndGetFullResponse("stratus_changeMinerMode", ["external"]); - expect(response.data.error.code).eq(-32603); + expect(response.data.error.code).eq(6002); expect(response.data.error.message.split("\n")[0]).to.equal( "Unexpected error: can't change miner mode from Interval without pausing it first", ); @@ -74,7 +74,7 @@ describe("Miner mode change integration test", function () { it("Miner change to Interval on Follower should fail because importer wasn't stopped", async function () { updateProviderUrl("stratus-follower"); const response = await sendAndGetFullResponse("stratus_changeMinerMode", ["1s"]); - expect(response.data.error.code).eq(-32603); + expect(response.data.error.code).eq(6002); expect(response.data.error.message).eq("Consensus is set."); }); @@ -97,14 +97,14 @@ describe("Miner mode change integration test", function () { it("Miner change on Leader without params should fail", async function () { updateProviderUrl("stratus"); const response = await sendAndGetFullResponse("stratus_changeMinerMode", []); - expect(response.data.error.code).eq(-32602); + expect(response.data.error.code).eq(1005); expect(response.data.error.message).eq("Expected String parameter, but received nothing."); }); it("Miner change on Leader with invalid params should fail", async function () { updateProviderUrl("stratus"); const response = await sendAndGetFullResponse("stratus_changeMinerMode", ["invalidMode"]); - expect(response.data.error.code).eq(-32602); + expect(response.data.error.code).eq(1009); expect(response.data.error.message).eq("Miner mode param is invalid."); }); @@ -123,7 +123,7 @@ describe("Miner mode change integration test", function () { it("Miner change on Leader to Automine should fail because it is not supported", async function () { updateProviderUrl("stratus"); const response = await sendAndGetFullResponse("stratus_changeMinerMode", ["automine"]); - expect(response.data.error.code).eq(-32603); + expect(response.data.error.code).eq(6002); expect(response.data.error.message.split("\n")[0]).eq( "Unexpected error: Miner mode change to 'automine' is unsupported.", ); @@ -167,7 +167,7 @@ describe("Miner mode change integration test", function () { // Change Miner mode to External on Leader with Pending Transactions should fail const changeMinerModeResponse = await sendAndGetFullResponse("stratus_changeMinerMode", ["external"]); - expect(changeMinerModeResponse.data.error.code).eq(-32603); + expect(changeMinerModeResponse.data.error.code).eq(6002); expect(changeMinerModeResponse.data.error.message).eq("There are (1) pending transactions."); // Clean up diff --git a/e2e/test/admin/e2e-admin-password-enabled.test.ts b/e2e/test/admin/e2e-admin-password-enabled.test.ts index 4687542b4..cabd6d2a4 100644 --- a/e2e/test/admin/e2e-admin-password-enabled.test.ts +++ b/e2e/test/admin/e2e-admin-password-enabled.test.ts @@ -9,14 +9,14 @@ describe("Admin Password (with password set)", () => { it("should reject requests without password", async () => { const error = await sendAndGetError("stratus_enableTransactions", []); - expect(error.code).eq(-32009); // Internal error + expect(error.code).eq(7004); // Internal error expect(error.message).to.contain("Incorrect password"); }); it("should reject requests with wrong password", async () => { const headers = { Authorization: "Password wrong123" }; const error = await sendAndGetError("stratus_enableTransactions", [], headers); - expect(error.code).eq(-32009); // Internal error + expect(error.code).eq(7004); // Internal error expect(error.message).to.contain("Incorrect password"); }); diff --git a/e2e/test/automine/e2e-json-rpc.test.ts b/e2e/test/automine/e2e-json-rpc.test.ts index b6fda44c1..c25dac8d2 100644 --- a/e2e/test/automine/e2e-json-rpc.test.ts +++ b/e2e/test/automine/e2e-json-rpc.test.ts @@ -325,7 +325,7 @@ describe("JSON-RPC", () => { it("fails on HTTP", async () => { const error = await sendAndGetError("eth_subscribe", ["newHeads"]); expect(error).to.not.be.null; - expect(error.code).eq(-32603); // Internal error + expect(error.code).eq(6002); // Internal error }); it("subscribes to newHeads receives success subscription event", async () => { const waitTimeInMilliseconds = 40; @@ -359,7 +359,7 @@ describe("JSON-RPC", () => { expect(response.error).to.not.be.undefined; expect(response.error.code).to.not.be.undefined; expect(response.error.code).to.be.a("number"); - expect(response.error.code).eq(-32602); + expect(response.error.code).eq(1006); }); it("validates newHeads event", async () => { diff --git a/e2e/test/external/e2e-json-rpc.test.ts b/e2e/test/external/e2e-json-rpc.test.ts index 9a981e80c..a923d6d63 100644 --- a/e2e/test/external/e2e-json-rpc.test.ts +++ b/e2e/test/external/e2e-json-rpc.test.ts @@ -483,7 +483,7 @@ describe("JSON-RPC", () => { it("fails on HTTP", async () => { const error = await sendAndGetError("eth_subscribe", ["newHeads"]); expect(error).to.not.be.null; - expect(error.code).eq(-32603); // Internal error + expect(error.code).eq(6002); // Internal error }); it("subscribes to newHeads receives success subscription event", async () => { const waitTimeInMilliseconds = 40; @@ -517,7 +517,7 @@ describe("JSON-RPC", () => { expect(response.error).to.not.be.undefined; expect(response.error.code).to.not.be.undefined; expect(response.error.code).to.be.a("number"); - expect(response.error.code).eq(-32602); + expect(response.error.code).eq(1006); }); it("validates newHeads event", async () => {