Skip to content

Commit a68e61f

Browse files
author
Nikolay
committed
Starknet. Refactoring and bug fixing
1 parent 8164bc4 commit a68e61f

File tree

14 files changed

+192
-49
lines changed

14 files changed

+192
-49
lines changed

lib/constructs/amb-ethereum-single-node.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ export interface SingleNodeAMBEthereumConstructCustomProps {
1313
export class SingleNodeAMBEthereumConstruct extends cdkContructs.Construct {
1414
public nodeId: string;
1515
public rpcUrl: string;
16+
public wssRpcUrl: string;
1617
public billingToken: string;
1718
public rpcUrlWithBillingToken: string;
19+
public wssRpcUrlWithBillingToken: string;
1820

1921

2022
constructor(scope: cdkContructs.Construct, id: string, props: SingleNodeAMBEthereumConstructCustomProps) {
@@ -63,8 +65,10 @@ export class SingleNodeAMBEthereumConstruct extends cdkContructs.Construct {
6365

6466
this.nodeId = createNode.getResponseField('NodeId');
6567
this.rpcUrl = `https://${this.nodeId}.t.ethereum.managedblockchain.${REGION}.amazonaws.com`;
68+
this.wssRpcUrl = `wss://${this.nodeId}.wss.t.ethereum.managedblockchain.${REGION}.amazonaws.com`;
6669
this.billingToken=createAccessor.getResponseField('BillingToken');
67-
this.rpcUrlWithBillingToken = `${this.rpcUrl}?billingtoken=${this.billingToken}`;
70+
this.rpcUrlWithBillingToken = `${this.rpcUrl}/?billingtoken=${this.billingToken}`;
71+
this.wssRpcUrlWithBillingToken = `${this.wssRpcUrl}/?billingtoken=${this.billingToken}`;
6872

6973
const deleteAccessor = new cr.AwsCustomResource(this, 'deleteAccessor', {
7074
onDelete: {

lib/starknet/.npmignore

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
*.ts
2-
!*.d.ts
1+
*.js
2+
!jest.config.js
3+
*.d.ts
4+
node_modules
35

46
# CDK asset staging directory
57
.cdk.staging
68
cdk.out
9+
.idea
10+
11+
*-node.json

lib/starknet/README.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,16 @@ We will use AWS Cloud9 to execute the subsequent commands. Follow the instructio
8787
> cdk bootstrap aws://ACCOUNT-NUMBER/REGION
8888
> ```
8989
90+
5. [OPTIONAL] If you are not planning to set your own `STARKNET_L1_ENDPOINT` URL, deploy Amazon Managed Blockchain (AMB) Access Ethereum node and wait about 35-70 minutes for the node to sync
9091
91-
5. Deploy Starknet Full Node
92+
```bash
93+
pwd
94+
# Make sure you are in aws-blockchain-node-runners/lib/starknet
95+
npx cdk deploy starknet-ethereum-l1-node --json --outputs-file starknet-ethereum-l1-node.json
96+
```
97+
To watch the progress, open the [AMB Web UI](https://console.aws.amazon.com/managedblockchain/home), click the name of your target network from the list (Mainnet, Goerly, etc.) and watch the status of the node to change from `Creating` to `Available`.
98+
99+
6. Deploy Starknet Full Node
92100
93101
```bash
94102
pwd
@@ -143,7 +151,9 @@ A script on the Starknet node publishes current block and blocks behind metrics
143151
144152
# Undeploy Single Node
145153
npx cdk destroy starknet-single-node
146-
154+
155+
# Undeploy AMB Etheruem node
156+
npx cdk destroy starknet-ethereum-l1-node
147157
148158
# Delete all common components like IAM role and Security Group
149159
npx cdk destroy starknet-common

lib/starknet/app.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
import 'dotenv/config'
33
import 'source-map-support/register';
44
import * as cdk from 'aws-cdk-lib';
5+
import * as nag from "cdk-nag";
56
import * as config from "./lib/config/starknetConfig";
67
import {StarknetCommonStack} from "./lib/common-stack";
8+
import {StarknetAMBEthereumSingleNodeStack} from "./lib/amb-ethereum-single-node-stack";
79
import {StarknetSingleNodeStack} from "./lib/single-node-stack";
810

911
const app = new cdk.App();
@@ -14,8 +16,16 @@ new StarknetCommonStack(app, "starknet-common", {
1416
env: { account: config.baseConfig.accountId, region: config.baseConfig.region },
1517
});
1618

19+
new StarknetAMBEthereumSingleNodeStack(app, "starknet-ethereum-l1-node", {
20+
stackName: `starknet-amb-ethereum-single-node-${config.baseNodeConfig.ambEntereumNodeNetworkId}`,
21+
env: { account: config.baseConfig.accountId, region: config.baseConfig.region },
22+
23+
ambEthereumNodeNetworkId: config.baseNodeConfig.ambEntereumNodeNetworkId,
24+
ambEthereumNodeInstanceType: config.baseNodeConfig.ambEntereumNodeInstanceType,
25+
});
26+
1727
new StarknetSingleNodeStack(app, "starknet-single-node", {
18-
stackName: `starknet-single-node`,
28+
stackName: `starknet-single-node-${config.baseNodeConfig.starknetNetworkId}`,
1929
env: { account: config.baseConfig.accountId, region: config.baseConfig.region },
2030

2131
instanceType: config.baseNodeConfig.instanceType,
@@ -25,3 +35,12 @@ new StarknetSingleNodeStack(app, "starknet-single-node", {
2535
starknetL1Endpoint: config.baseNodeConfig.starknetL1Endpoint,
2636
starknetNodeVersion: config.baseNodeConfig.starknetNodeVersion,
2737
});
38+
39+
// Security Check
40+
cdk.Aspects.of(app).add(
41+
new nag.AwsSolutionsChecks({
42+
verbose: false,
43+
reports: true,
44+
logIgnores: false,
45+
})
46+
);
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import * as cdk from "aws-cdk-lib";
2+
import * as cdkConstructs from "constructs";
3+
import * as nag from "cdk-nag";
4+
import * as configTypes from "./config/starknetConfig.interface";
5+
import { SingleNodeAMBEthereumConstruct } from "../../constructs/amb-ethereum-single-node";
6+
7+
export interface ScrollAMBEthereumSingleNodeStackProps extends cdk.StackProps {
8+
ambEthereumNodeNetworkId: configTypes.AMBEthereumNodeNetworkId,
9+
ambEthereumNodeInstanceType: string,
10+
}
11+
12+
export class StarknetAMBEthereumSingleNodeStack extends cdk.Stack {
13+
constructor(scope: cdkConstructs.Construct, id: string, props: ScrollAMBEthereumSingleNodeStackProps) {
14+
super(scope, id, props);
15+
16+
// Setting up necessary environment variables
17+
const availabilityZones = cdk.Stack.of(this).availabilityZones;
18+
const chosenAvailabilityZone = availabilityZones.slice(0, 1)[0];
19+
20+
// Getting our config from initialization properties
21+
const {
22+
ambEthereumNodeNetworkId,
23+
ambEthereumNodeInstanceType,
24+
} = props;
25+
26+
// Setting up L1 Ethereum node with AMB Ethereum node construct
27+
28+
const ambEthereumNode = new SingleNodeAMBEthereumConstruct(this, "amb-ethereum-l1-single-node", {
29+
instanceType: ambEthereumNodeInstanceType,
30+
availabilityZone: chosenAvailabilityZone,
31+
ethNetworkId: ambEthereumNodeNetworkId,
32+
})
33+
34+
new cdk.CfnOutput(this, "amb-eth-node-id", {
35+
value: ambEthereumNode.nodeId,
36+
exportName: "AmbEthereumNodeId"
37+
});
38+
39+
new cdk.CfnOutput(this, "amb-eth-node-rpc-url-billing-token", {
40+
value: ambEthereumNode.wssRpcUrlWithBillingToken,
41+
exportName: "AmbEthereumNodeRpcUrlWithBillingToken",
42+
});
43+
44+
// Adding suppressions to the stack
45+
nag.NagSuppressions.addResourceSuppressions(
46+
this,
47+
[
48+
{
49+
id: "AwsSolutions-IAM5",
50+
reason: "Need to create custom resources to Create and Delete AMB node and accessor and IAM policy to support a generic case for AMB resources",
51+
},
52+
{
53+
id: "AwsSolutions-IAM4",
54+
reason: "Need to create custom resources to Create and Delete AMB node and accessor and IAM to support ti",
55+
},
56+
],
57+
true
58+
);
59+
}
60+
}
Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
#!/bin/bash
2+
3+
source /etc/environment
4+
5+
# Get local IP
6+
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
7+
export EC2_INTERNAL_IP=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s "http://169.254.169.254/latest/meta-data/local-ipv4")
8+
29
# Start Juno node
310
/home/ubuntu/juno-source/build/juno \
4-
--db-path "/home/ubuntu/juno-source/juno-datadir" \
11+
--db-path "/data/juno" \
512
--http \
6-
--http-host 0.0.0.0 \
13+
--http-host "${EC2_INTERNAL_IP}" \
714
--http-port 6060 \
8-
--network ${_STARKNET_NETWORK_ID_} \
9-
--eth-node ${_STARKNET_L1_ENDPOINT_}
15+
--network ${STARKNET_NETWORK_ID} \
16+
--eth-node ${STARKNET_L1_ENDPOINT}

lib/starknet/lib/assets/sync-checker/syncchecker-starknet.sh

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
#!/bin/bash
22

3+
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
4+
EC2_INTERNAL_IP=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s "http://169.254.169.254/latest/meta-data/local-ipv4")
5+
36
# Getting syncing status from Starknet node
4-
STARKNET_SYNC_STATS=$(curl -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"starknet_syncing","params":[],"id":1}' http://localhost:6060 | jq -r ".result")
7+
STARKNET_SYNC_STATS=$(curl -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"starknet_syncing","params":[],"id":1}' http://$EC2_INTERNAL_IP:6060 | jq -r ".result")
58

69
if [[ "$STARKNET_SYNC_STATS" == "false" ]]; then
710
echo "Node is fully synced. No syncing data available."
@@ -16,11 +19,11 @@ else
1619
echo "Highest Block: $STARKNET_HIGHEST_BLOCK"
1720
fi
1821

19-
STARKNET_BLOCKS_BEHIND=$(($STARKNET_HIGHEST_BLOCK - $STARKNET_CURRENT_BLOCK))
22+
STARKNET_BLOCKS_BEHIND="$((STARKNET_HIGHEST_BLOCK-STARKNET_CURRENT_BLOCK))"
23+
2024
echo "STARKNET_BLOCKS_BEHIND Block: $STARKNET_BLOCKS_BEHIND"
2125

2226
# Sending data to CloudWatch
23-
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
2427
INSTANCE_ID=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-id)
2528
REGION=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq .region -r)
2629
TIMESTAMP=$(date +"%Y-%m-%dT%H:%M:%S%z")

lib/starknet/lib/assets/user-data/node.sh

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
#!/bin/bash
22
set +e
33

4-
echo "AWS_REGION=${_AWS_REGION_}" >> /etc/environment
5-
echo "ASSETS_S3_PATH=${_ASSETS_S3_PATH_}" >> /etc/environment
6-
echo "STACK_NAME=${_STACK_NAME_}" >> /etc/environment
7-
echo "STACK_ID=${_STACK_ID_}" >> /etc/environment
8-
echo "RESOURCE_ID=${_NODE_CF_LOGICAL_ID_}" >> /etc/environment
9-
echo "DATA_VOLUME_TYPE=${_DATA_VOLUME_TYPE_}" >> /etc/environment
10-
echo "DATA_VOLUME_SIZE=${_DATA_VOLUME_SIZE_}" >> /etc/environment
11-
echo "STARKNET_NODE_VERSION=${_STARKNET_NODE_VERSION_}" >> /etc/environment
12-
echo "STARKNET_NETWORK_ID=${_STARKNET_NETWORK_ID_}" >> /etc/environment
13-
echo "STARKNET_L1_ENDPOINT=${_STARKNET_L1_ENDPOINT_}" >> /etc/environment
4+
{
5+
echo "AWS_REGION=${_AWS_REGION_}"
6+
echo "ASSETS_S3_PATH=${_ASSETS_S3_PATH_}"
7+
echo "STACK_NAME=${_STACK_NAME_}"
8+
echo "STACK_ID=${_STACK_ID_}"
9+
echo "RESOURCE_ID=${_NODE_CF_LOGICAL_ID_}"
10+
echo "DATA_VOLUME_TYPE=${_DATA_VOLUME_TYPE_}"
11+
echo "DATA_VOLUME_SIZE=${_DATA_VOLUME_SIZE_}"
12+
echo "STARKNET_NODE_VERSION=${_STARKNET_NODE_VERSION_}"
13+
echo "STARKNET_NETWORK_ID=${_STARKNET_NETWORK_ID_}"
14+
echo "STARKNET_L1_ENDPOINT=${_STARKNET_L1_ENDPOINT_}"
15+
} >> /etc/environment
16+
1417
source /etc/environment
1518

16-
sudo apt-get -yqq update
17-
sudo apt-get -yqq install -y build-essential cargo pkg-config git upx-ucl libjemalloc-dev libjemalloc2 awscli jq unzip python3-pip
19+
apt-get -yqq update
20+
apt-get -yqq install -y build-essential cargo pkg-config git upx-ucl libjemalloc-dev libjemalloc2 awscli jq unzip python3-pip
1821

1922
cd /opt
2023

@@ -25,14 +28,14 @@ unzip -q assets.zip
2528

2629
echo "Install and configure CloudWatch agent"
2730
wget -q https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb
28-
sudo dpkg -i -E amazon-cloudwatch-agent.deb
31+
dpkg -i -E amazon-cloudwatch-agent.deb
2932

3033
echo 'Configuring CloudWatch Agent'
3134
mkdir -p /opt/aws/amazon-cloudwatch-agent/etc/
3235
cp /opt/cw-agent.json /opt/aws/amazon-cloudwatch-agent/etc/custom-amazon-cloudwatch-agent.json
3336

3437
echo "Starting CloudWatch Agent"
35-
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
38+
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
3639
-a fetch-config -c file:/opt/aws/amazon-cloudwatch-agent/etc/custom-amazon-cloudwatch-agent.json -m ec2 -s
3740
systemctl status amazon-cloudwatch-agent
3841

@@ -68,30 +71,31 @@ echo "Waiting for volumes to be available"
6871
sleep 60
6972

7073
echo "Install Juno Starknet agent"
71-
pwd
72-
whoami
74+
7375
cd /home/ubuntu
74-
pwd
76+
7577
git clone --branch $STARKNET_NODE_VERSION --single-branch https://github.com/NethermindEth/juno.git juno-source
7678
cd /home/ubuntu/juno-source
7779

7880
echo "Preparing EBS Volume"
7981
DATA_VOLUME_ID=/dev/$(lsblk -lnb | awk -v VOLUME_SIZE_BYTES="$DATA_VOLUME_SIZE" '{if ($4== VOLUME_SIZE_BYTES) {print $1}}')
80-
sudo mkfs -t xfs $DATA_VOLUME_ID
82+
mkfs -t xfs $DATA_VOLUME_ID
8183
sleep 10
8284
DATA_VOLUME_UUID=$(lsblk -fn -o UUID $DATA_VOLUME_ID)
83-
DATA_VOLUME_FSTAB_CONF="UUID=$DATA_VOLUME_UUID /home/ubuntu/juno-source/juno-datadir xfs defaults 0 2"
85+
DATA_VOLUME_FSTAB_CONF="UUID=$DATA_VOLUME_UUID /data xfs defaults 0 2"
8486
echo "DATA_VOLUME_ID="$DATA_VOLUME_ID
8587
echo "DATA_VOLUME_UUID="$DATA_VOLUME_UUID
8688
echo "DATA_VOLUME_FSTAB_CONF="$DATA_VOLUME_FSTAB_CONF
8789
echo $DATA_VOLUME_FSTAB_CONF | sudo tee -a /etc/fstab
88-
sudo mkdir "juno-datadir"
89-
sudo mount -a
90+
mkdir "/data"
91+
mkdir "/data/juno"
92+
mount -a
93+
chown ubuntu:ubuntu -R /data
9094

9195
echo "Install Go 1.22 Version"
92-
sudo snap info go
93-
sudo snap install go --channel=1.22/stable --classic
94-
whereis go
96+
snap info go
97+
snap install go --channel=1.22/stable --classic
98+
9599
export GOPATH=/snap/bin/go
96100
go env|grep CACHE
97101
sudo su - ubuntu
@@ -139,10 +143,26 @@ EOF'
139143
sudo systemctl daemon-reload
140144
sudo systemctl enable --now starknet
141145

146+
# Configuring logrotate
147+
sudo bash -c 'sudo cat > logrotate.starkneterr <<EOF
148+
/var/log/starknet/error.log {
149+
rotate 7
150+
daily
151+
missingok
152+
postrotate
153+
systemctl kill -s USR1 starknet.service
154+
endscript
155+
}
156+
EOF'
157+
158+
sudo cp logrotate.starkneterr /etc/logrotate.d/starkneterr
159+
sudo systemctl restart logrotate.service
160+
142161
echo "Configuring syncchecker script"
143162
cd /opt
144163
sudo mv /opt/sync-checker/syncchecker-starknet.sh /opt/syncchecker.sh
145164
sudo chmod +x /opt/syncchecker.sh
146165

147-
(crontab -l; echo "*/1 * * * * /opt/syncchecker.sh >/tmp/syncchecker.log 2>&1") | crontab -
166+
echo "*/5 * * * * /opt/syncchecker.sh" | crontab
148167
crontab -l
168+
echo "All done!"

lib/starknet/lib/config/starknetConfig.interface.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import * as configTypes from "../../../constructs/config.interface";
33
export type StarknetNetworkId = "mainnet" | "sepolia" | "sepolia-integration";
44
export type StarknetL1Endpoint = string;
55

6+
export {AMBEthereumNodeNetworkId} from "../../../constructs/config.interface";
7+
68
export interface StarknetDataVolumeConfig extends configTypes.DataVolumeConfig {
79
}
810

@@ -13,6 +15,8 @@ export interface StarknetBaseConfig extends configTypes.BaseConfig {
1315
}
1416

1517
export interface StarknetBaseNodeConfig extends configTypes.BaseNodeConfig {
18+
ambEntereumNodeNetworkId: configTypes.AMBEthereumNodeNetworkId;
19+
ambEntereumNodeInstanceType: string;
1620
starknetL1Endpoint: StarknetL1Endpoint;
1721
starknetNetworkId: StarknetNetworkId;
1822
starknetNodeVersion: string;

lib/starknet/lib/config/starknetConfig.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,17 @@ export const baseConfig: configTypes.StarknetBaseConfig = {
2424
}
2525

2626
export const baseNodeConfig: configTypes.StarknetBaseNodeConfig = {
27-
27+
ambEntereumNodeNetworkId: <configTypes.AMBEthereumNodeNetworkId> process.env.AMB_ENTEREUM_NODE_NETWORK_ID || "mainnet",
28+
ambEntereumNodeInstanceType: process.env.AMB_ETHEREUM_NODE_INSTANCE_TYPE || "bc.m5.xlarge",
2829
instanceType: new ec2.InstanceType(process.env.STARKNET_INSTANCE_TYPE ? process.env.STARKNET_INSTANCE_TYPE : "m6a.2xlarge"),
2930
instanceCpuType: ec2.AmazonLinuxCpuType.X86_64,
3031
starknetNetworkId: <configTypes.StarknetNetworkId> process.env.STARKNET_NETWORK_ID || "mainnet",
3132
starknetNodeVersion: process.env.STARKNET_NODE_VERSION || "v0.11.7",
32-
starknetL1Endpoint: process.env.STARKNET_L1_ENDPOINT || "ws://eth-mainnet.rpc.nethermind.io/ws",
33+
starknetL1Endpoint: process.env.STARKNET_L1_ENDPOINT || constants.NoneValue,
3334
dataVolume: {
3435
sizeGiB: process.env.STARKNET_DATA_VOL_SIZE ? parseInt(process.env.STARKNET_DATA_VOL_SIZE): 250,
3536
type: parseDataVolumeType(process.env.STARKNET_DATA_VOL_TYPE?.toLowerCase() ? process.env.STARKNET_DATA_VOL_TYPE?.toLowerCase() : "gp3"),
3637
iops: process.env.STARKNET_DATA_VOL_IOPS ? parseInt(process.env.STARKNET_DATA_VOL_IOPS): 3000,
37-
throughput: process.env.STARKNET_DATA_VOL_THROUGHPUT ? parseInt(process.env.STARKNET_DATA_VOL_THROUGHPUT): 700,
38+
throughput: process.env.STARKNET_DATA_VOL_THROUGHPUT ? parseInt(process.env.STARKNET_DATA_VOL_THROUGHPUT): 250,
3839
},
3940
};

0 commit comments

Comments
 (0)