From b55c8dba1ce0f399c44e730f8314c1d5565a1879 Mon Sep 17 00:00:00 2001 From: Doris Benda Date: Thu, 4 Jan 2024 16:12:19 +0100 Subject: [PATCH] Check for account aliases --- sponsoredTransactionsAuction/Dockerfile | 13 +++++----- sponsoredTransactionsAuction/README.md | 2 +- .../backend/README.md | 15 ++++++------ .../backend/src/main.rs | 12 +++++++--- .../backend/src/types.rs | 2 ++ .../frontend/src/components/Bid.tsx | 6 ++++- .../frontend/src/components/ViewItem.tsx | 24 +++++++++++-------- 7 files changed, 45 insertions(+), 29 deletions(-) diff --git a/sponsoredTransactionsAuction/Dockerfile b/sponsoredTransactionsAuction/Dockerfile index 82c63b2b..719fae37 100644 --- a/sponsoredTransactionsAuction/Dockerfile +++ b/sponsoredTransactionsAuction/Dockerfile @@ -1,14 +1,13 @@ ARG node_base_image=node:18-slim -ARG rust_base_image=rust:1.65 +ARG rust_base_image=rust:1.67 -FROM ${node_base_image} AS frontend +FROM ${node_base_image} AS front_end WORKDIR /app COPY ./sponsoredTransactionsAuction/frontend/package.json ./package.json COPY ./sponsoredTransactionsAuction/frontend/tsconfig.node.json ./tsconfig.node.json COPY ./sponsoredTransactionsAuction/frontend/tsconfig.json ./tsconfig.json COPY ./sponsoredTransactionsAuction/frontend/vite.config.ts ./vite.config.ts -COPY ./sponsoredTransactionsAuction/frontend/public ./public COPY ./sponsoredTransactionsAuction/frontend/src ./src COPY ./sponsoredTransactionsAuction/frontend/index.html ./index.html COPY ./sponsoredTransactionsAuction/frontend/generated ./generated @@ -16,7 +15,7 @@ COPY ./sponsoredTransactionsAuction/frontend/generated ./generated RUN yarn RUN yarn build -FROM ${rust_base_image} AS backend +FROM ${rust_base_image} AS back_end WORKDIR /backend/app COPY ./deps/concordium-rust-sdk /deps/concordium-rust-sdk @@ -27,7 +26,7 @@ RUN cargo build --release FROM ubuntu:22.04 WORKDIR /build -COPY --from=backend ./backend/app/target/release/sponsored-transaction-backend ./sponsored-transaction-backend -COPY --from=frontend ./app/dist ./public +COPY --from=back_end ./backend/app/target/release/sponsored-transaction-backend ./sponsored-transaction-backend +COPY --from=front_end ./app/dist ./public -CMD ./sponsored-transaction-backend --public-folder public \ No newline at end of file +CMD ./sponsored-transaction-backend --frontend public diff --git a/sponsoredTransactionsAuction/README.md b/sponsoredTransactionsAuction/README.md index 675f1281..20adbc35 100644 --- a/sponsoredTransactionsAuction/README.md +++ b/sponsoredTransactionsAuction/README.md @@ -34,7 +34,7 @@ docker run -p 8080:8080 --mount type=bind,source="$(pwd)"/,tar e.g. ```shell -docker run -p 8080:8080 --mount type=bind,source="$(pwd)"/4SizPU2ipqQQza9Xa6fUkQBCDjyd1vTNUNDGbBeiRGpaJQc6qX.export,target=/KEY,readonly -e ACCOUNT_KEY_FILE=/KEY -e PORT=8080 -e NODE=http://node.testnet.concordium.com:20000 -e LOG_LEVEL=info -e CIS2_TOKEN_CONTRACT_INDEX=7370 -e AUCTION_CONTRACT_INDEX=7415 sponsored_transactions +docker run -p 8080:8080 --mount type=bind,source="$(pwd)"/4SizPU2ipqQQza9Xa6fUkQBCDjyd1vTNUNDGbBeiRGpaJQc6qX.export,target=/KEY,readonly -e ACCOUNT_KEY_FILE=/KEY -e PORT=8080 -e NODE=http://node.testnet.concordium.com:20000 -e LOG_LEVEL=debug -e CIS2_TOKEN_CONTRACT_INDEX=7370 -e AUCTION_CONTRACT_INDEX=7415 sponsored_transactions ``` Note: To get your `ACCOUNT_KEY_FILE` (the `4SizPU2ipqQQza9Xa6fUkQBCDjyd1vTNUNDGbBeiRGpaJQc6qX.export` file), export it from the Concordium Browser Wallet for Web. diff --git a/sponsoredTransactionsAuction/backend/README.md b/sponsoredTransactionsAuction/backend/README.md index fd54fa86..01f463f8 100644 --- a/sponsoredTransactionsAuction/backend/README.md +++ b/sponsoredTransactionsAuction/backend/README.md @@ -6,27 +6,28 @@ This page describes the sponsored transactions backend for this dapp example. The following parameters are supported - `node` the URL of the node's GRPC V2 interface, e.g., `http://node.testnet.concordium.com:20000` -- `port` the port on which the server will listen for incoming requests -- `log-level` maximum log level (defaults to `debug` if not given) -- `public-folder` the path to the folder, which should be served, defaults to the `public` folder in the current directory. +- `port` the port on which the server will listen for incoming requests, e.g., 127.0.0.1:8080. +- `log-level` maximum log level (defaults to `debug` if not given). +- `frontend` the path to the folder, which should be served, defaults to the `public` folder in the current directory. - `account-key-file` the path to a file which contains the key credentials. - `cis2-token-smart-contract-index` the smart contract index which the sponsored transaction is submitted to. - `auction-smart-contract-index` the smart contract index of the auction smart contract. +- `request-timeout` the request timeout (both of request to the node and server requests) in milliseconds. The node timeout is 500 ms less than the request-timeout to make sure we can fail properly in the server in case of connection timeout due to node connectivity problems. All of the above is available by using `--help` to get usage information. An example to run the backend with basic settings and testnet node would be: ```shell -cargo run -- --node http://node.testnet.concordium.com:20000 --account-key-file --cis2-token-smart-contract-index 7370 --auction-smart-contract-index 7415 +cargo run -- --node http://node.testnet.concordium.com:20000 --account-key-file --cis2-token-smart-contract-index 7370 --auction-smart-contract-index 7415 --log-level debug ``` An example to run the backend with some filled in example settings would be: ```shell -cargo run -- --node http://node.testnet.concordium.com:20000 --cis2-token-smart-contract-index 7370 --auction-smart-contract-index 7415 --account-key-file ./4SizPU2ipqQQza9Xa6fUkQBCDjyd1vTNUNDGbBeiRGpaJQc6qX.export --log-level debug +cargo run -- --node http://node.testnet.concordium.com:20000 --account-key-file ./4SizPU2ipqQQza9Xa6fUkQBCDjyd1vTNUNDGbBeiRGpaJQc6qX.export --cis2-token-smart-contract-index 7370 --auction-smart-contract-index 7415 --log-level debug ``` -To get your account file (the `3PXwJYYPf6fyVb4GJquxSZU8puxrHfzc4XogdMVot8MUQK53tW.export` file in the above example), export it from the Concordium Browser wallet for web. +To get your account file (the `4SizPU2ipqQQza9Xa6fUkQBCDjyd1vTNUNDGbBeiRGpaJQc6qX.export` file in the above example), export it from the Concordium Browser wallet for web. @@ -46,7 +47,7 @@ The smart contract code at {index: CIS2_TOKEN_CONTRACT_INDEX, subindex: 0} can b The smart contract code at {index: AUCTION_CONTRACT_INDEX, subindex: 0} can be found [here](https://github.com/Concordium/concordium-rust-smart-contracts/tree/main/examples/sponsored-tx-enabled-auction). See [src/main.rs](./src/main.rs) for the formats of requests and responses. Both -requests and responses are JSON encoded. The requests are handled by handlers in [src/handlers.rs](./src/handlers.rs). +requests and responses are JSON encoded. # Contributing diff --git a/sponsoredTransactionsAuction/backend/src/main.rs b/sponsoredTransactionsAuction/backend/src/main.rs index 1ac9d802..f1daac4d 100644 --- a/sponsoredTransactionsAuction/backend/src/main.rs +++ b/sponsoredTransactionsAuction/backend/src/main.rs @@ -62,7 +62,7 @@ struct App { #[clap( long = "request-timeout", help = "Request timeout (both of request to the node and server requests) in milliseconds.", - default_value = "5000", + default_value = "10000", env = "REQUEST_TIMEOUT" )] request_timeout: u64, @@ -183,7 +183,6 @@ async fn main() -> anyhow::Result<()> { // Render index.html let index_template = fs::read_to_string(app.frontend_assets.join("index.html")) .context("Frontend was not built or wrong path to the frontend files.")?; - tracing::info!("Starting server..."); let serve_dir_service = ServeDir::new(app.frontend_assets.join("assets")); let router = Router::new() @@ -365,7 +364,14 @@ async fn handle_signature_bid( let mut rate_limits = state.rate_limits.lock().await; - let limit = rate_limits.entry(request.signer).or_insert(0u8); + // Account addresses on Concordium have account aliases. We track the + // rate-limits by using the alias 0 for every account. https://developer.concordium.software/en/mainnet/net/references/transactions.html#account-aliases + let alias_account_0 = request + .signer + .get_alias(0) + .ok_or_else(|| ServerError::NoAliasAccount)?; + + let limit = rate_limits.entry(alias_account_0).or_insert(0u8); if *limit >= RATE_LIMIT_PER_ACCOUNT { tracing::warn!("Rate limit for account {} reached.", request.signer); diff --git a/sponsoredTransactionsAuction/backend/src/types.rs b/sponsoredTransactionsAuction/backend/src/types.rs index 2f15d957..890fa852 100644 --- a/sponsoredTransactionsAuction/backend/src/types.rs +++ b/sponsoredTransactionsAuction/backend/src/types.rs @@ -32,6 +32,8 @@ pub enum ServerError { RateLimitError, #[error("Unable to submit transaction on chain successfully: {0}")] SubmitSponsoredTransactionError(#[from] RPCError), + #[error("Unable to derive alias account of signer.")] + NoAliasAccount, } impl axum::response::IntoResponse for ServerError { diff --git a/sponsoredTransactionsAuction/frontend/src/components/Bid.tsx b/sponsoredTransactionsAuction/frontend/src/components/Bid.tsx index f4114535..514902e0 100644 --- a/sponsoredTransactionsAuction/frontend/src/components/Bid.tsx +++ b/sponsoredTransactionsAuction/frontend/src/components/Bid.tsx @@ -31,7 +31,11 @@ async function generateTransferMessage( itemIndexAuction: string, ) { try { - const viewItemStateParam: AuctionContract.ViewItemStateParameter = itemIndexAuction as unknown as number; + const viewItemStateParam: AuctionContract.ViewItemStateParameter = Number(itemIndexAuction); + + if (Number.isNaN(viewItemStateParam)) { + throw new Error(`ItemIndex is NaN.`); + } const itemState: AuctionContract.ReturnValueViewItemState = await viewItemState(viewItemStateParam); diff --git a/sponsoredTransactionsAuction/frontend/src/components/ViewItem.tsx b/sponsoredTransactionsAuction/frontend/src/components/ViewItem.tsx index 4ace9f11..03818270 100644 --- a/sponsoredTransactionsAuction/frontend/src/components/ViewItem.tsx +++ b/sponsoredTransactionsAuction/frontend/src/components/ViewItem.tsx @@ -33,16 +33,20 @@ export default function ViewItem(props: ConnectionProps) { const viewItemStateParam: AuctionContract.ViewItemStateParameter = Number(data.itemIndex); - if (grpcClient) { - viewItemState(viewItemStateParam) - .then((returnValue) => { - if (returnValue !== undefined) { - setItemState(JSONbig.stringify(returnValue)); - } - }) - .catch((e) => { - setItemStateError((e as Error).message); - }); + if (Number.isNaN(viewItemStateParam)) { + setItemStateError('ItemIndex is NaN.'); + } else { + if (grpcClient) { + viewItemState(viewItemStateParam) + .then((returnValue) => { + if (returnValue !== undefined) { + setItemState(JSONbig.stringify(returnValue)); + } + }) + .catch((e) => { + setItemStateError((e as Error).message); + }); + } } }