Towns 백서

Towns

원문

bitpro가 원문에서 글자만 모은 내용이에요. 표·그림·수식은 빠지거나 깨질 수 있어요. 전체 17쪽 중 11쪽

rt-contracts/the-diamond-standard-eip-2535-explained-part-1) pattern. This means for practical purposes that when interacting with contracts on Base or Towns Chain, you will be calling each method on the associated diamond contract.</Note> ### Registration Outline The following outlines the logical steps to onboarding a Node FE with attached storage from 0 to 1. Instructions are applicable to testnet and mainnet. Instructions with specific calling signatures can be found below in the [Node FE Registration](#node-fe-registration) sections. Please ensure you have completed [Node Operator registration](/node-operator/tutorials/register-towns-operator) before proceeding with node registration. <Steps> <Step title="Start Stream Node in Info Mode">Operator should start the stream node process in [info](https://github.com/towns-protocol/towns/tree/main/core/node#checking-on-gamma-status-from-local-host) mode and additionally ensure DNS, TLS, and network are configured correctly.</Step> <Step title="Register Node in Towns Chain">Operator calls [registerNode](https://github.com/towns-protocol/towns/blob/main/packages/contracts/src/river/registry/facets/node/NodeRegistry.sol) on the [RiverRegistry](https://github.com/towns-protocol/towns/blob/main/packages/contracts/deployments/gamma/river/addresses/riverRegistry.json) diamond contract deployed on Towns Chain once health checks pass.</Step> <Step title="Register Node in Base">Operator calls [registerNode](https://github.com/towns-protocol/towns/blob/main/packages/contracts/src/base/registry/facets/checker/EntitlementChecker.sol) on the BaseRegistry diamond contract to support cross-chain checks.</Step> <Step title="Start Stream Node">Operator starts the stream node by running the docker image to enter Towns Chain network once registered.</Step> </Steps> ### Node FE Registration Once a node operator has registered their operator address on Towns Chain, they can proceed to register their nodes. Nodes are registered individually on Towns Chain and Base. <Warning> Node Operator addresses must be registered on Towns Chain before below actions can be undertaken to register a new stream node. DAO will migrate operator address to Towns Chain once sufficient delegations are received. </Warning> Once a node is setup, attached to postgres storage, network configured with a public IP, and passing health checks (see [System Requirements & Installation](/node-operator/tutorials/system-requirements-installation)), the node is ready to enter the Towns Network and begin accepting stream writes. Registering a node on Towns Chain, can be accomplished by calling the `registerNode(address,string,uint8)` method on the RiverRegistry diamond contract. <Warning> Registering a node and operating a stream node in general requires that the node wallet has Eth for the target network (Sepolia Eth for testnet, Eth for mainnet) to pay for gas. On testnet, sepolia eth can be obtained from a [faucet](https://towns-devnet.hub.caldera.xyz/). Stream nodes should also have a wallet on Base with Base Eth (mainnet) or Base Sepolia Eth (testnet) to pay for gas when committing cross-chain transactions. </Warning> The below steps describe how to register a new node URL in `Operational` status using `cast`, a command-line tool that is part of Foundry for reading / writing to EVM chains over RPC url's. <Note> Setting a Node to `Operational` status will allow the node to begin accepting stream writes and signal to the network that the node is healthy and ready to be connected to by clients. See all possible node statuses that a node can assume in [RegistryStorage](https://github.com/towns-protocol/towns/blob/main/packages/contracts/src/river/registry/libraries/RegistryStorage.sol#L30). </Note> <Steps> <Step title="Setup Variables for Registration"> ```bash theme={null} # checkout repo and extract RiverRegistry deployed address $ git clone git@github.com:towns-protocol/towns.git $ cd river $ JSON_FILE="packages/generated/deployments/testnet/river/addresses/riverRegistry.json" $ RIVER_REGISTRY_ADDRESS=$(jq -r '.address' "$JSON_FILE") # set node address, which is wallet address of node's ECDSA wallet created on configuration. NODE_ADDRESS=<Node FE Wallet Address> PRIVATE_KEY=<Node Operator private key> # node url NODE_URL=<public node url pointing to a single public IP address that represents running Node FE pid> # set RPC_URL to point to testnet RPC_URL=https://devnet.rpc.river.build # set BASE_RPC_URL to point to base testnet BASE_RPC_URL=https://base-sepolia.g.alchemy.com/v2/${RPC_KEY} ``` <br /> <Warning>Private Key needed for cast call is Node Operator's not Node FE's. It is up to Node Operator how they decide to secure this key and make it available to perform cast calls to register nodes.</Warning> </Step> <Step title="Register Node on Base and Towns Chain"> Using `cast` let's register our new node. First let's check that the Node FE does not already exist. Node FE's are identified in Towns Registry by their address so let's check `getNode` to ensure the view reverts with `NODE_NOT_FOUND` before proceeding. ```bash theme={null} cast call --rpc-url $RPC_URL \ $RIVER_REGISTRY_ADDRESS \ "getNode(address)" \ $NODE_ADDRESS ``` Assuming the above reverts with `NODE_NOT_FOUND`, let's proceed to register the new node with the Node Operator's wallet. <br /> <Note>Registering a new node is a write transaction that will require the Node Operator wallet on Towns Chain and Base has Eth. To monitor Towns Chain transactions, you can use the [explorer](https://explorer.river.build/).</Note> ```bash theme={null} # Register a new node with EntitlementChecker in Base to ensure xchain entitlements are in place when running stream node. # Note: EntitlementChecker is a facet and so call it's interface from Base Registry diamond contract (for address see baseRegistry.json under packages/generated/deployments in river repo). # Ensure you call the below with the Node Operator wallet you have registered on Base. NODE_ADDRESS is the wallet address of the Node FE. cast send \ --rpc-url $BASE_RPC_URL \ --private-key $PRIVATE_KEY \ $BASE_REGISTRY_ADDRESS \ "registerNode(address)" \ $NODE_ADDRESS ``` <br /> ```bash theme={null} # Register a new node in Operational (2) Status in Towns Chain to signal to the network the node is ready to accept reads and writes. cast send \ --rpc-url $RPC_URL \ --private-key $PRIVATE_KEY \ $RIVER_REGISTRY_ADDRESS \ "registerNode(address,string,uint8)" \ $NODE_ADDRESS \ $NODE_URL \ 2 ``` <Warning>When registering node, make sure you pass in the node url including the schema of the url, which must be https\://. For example, for node referenced by domain name, river-operator-1.xyz, you would pass in the node url to registerNode call as [https://river-operator-1.xyz](https://river-operator-1.xyz). Therefore, prior to calling registerNode using Operational status, you must ensure the node url resolves from the public internet.</Warning> When the above transactions succeed and have been mined in a block on Towns Chain, you can re-run `getNode(address)` to confirm the node now exists in the network. </Step> <Step title="Check Node Health from Debug Multi Dashboard"> To check that your node is included in the network and healthy, you can navigate to: `$NODE_URL/debug/multi` in a browser to see the node's http1/2, grpc ping status and related health metrics. As an example, see [https://ohare-3.staking.production.figment.io/debug/multi](https://ohare-3.staking.production.figment.io/debug/multi). </Step> </Steps> # System Configuration Source: https://docs.towns.com/node-operator/tutorials/system-configuration-steps The following guide describes steps and best practices for configuring a Towns Stream Node after meeting the [system requirements](/node-operator/tutorials/system-requirements-installation). ## Node FE & Storage Configuration <Steps> <Step title="Generate configuration associated with the Node Storage"> Generate an ECDSA wallet that will serve as the Node identity to the storage layer and network. On Node FE startup, this wallet will be used to access the appropriate database schema and to authenticate the Node FE to the Towns Chain during registration. <Note>Only one unique Node FE (by wallet identity) can be associated with a Node Storage instance at a given time.</Note> <AccordionGroup> <Accordion title="Generate node wallet identity with cast"> Wallets can quickly be generated on the command line with `cast`. ```bash theme={null} # generate a new wallet to console in json format $ cast wallet n -j ``` </Accordion> <Accordion title="Generate node wallet identity with ethers.js"> Wallets can also be generated with [ethers.js](https://github.com/ethers-io/ethers.js) package in javascript. See below for an example in javascript. ```bash theme={null} # check if node is installed $ node -v # installs ethers.js $ npm i ethers ``` Then copy-paste the below into a file, `address.js`. Run with `node address.js` to generate a new wallet and print key to console. ```javascript theme={null} var ethers = require('ethers'); var crypto = require('crypto'); var id = crypto.randomBytes(32).toString('hex'); var privateKey = "0x"+id; console.log("SAVE BUT DO NOT SHARE THIS:", privateKey); var wallet = new ethers.Wallet(privateKey); console.log("Address: " + wallet.address); ``` </Accordion> </AccordionGroup> </Step> <Step title="Generate configuration associated with the Node FE"> During this step, configure your Node FE image or binary to run in your networked environment that has connectivity to the Node Storage instance and set your Node FE environment variables, such as RPC\_URL's, logging level, contract addresses. Some of the required environment variables will be secrets as described in [system requirements](/node-operator/tutorials/system-requirements-installation#node-fe-environment-variables) that will need to be stored and injected in your runtime securely. Choices around secret storage depend largely on the cloud or on-premise hosting environment for the Node FE, which is left up to the node operator. </Step> <Step title="Node Front End (FE)"> Configure your Node FE with a publicly addressable, static IPv4 host, ensuring it can serve HTTP1.1 & HTTP2 requests. If behind a termination proxy, configure accordingly. Ensure your network does not proxy traffic through an ALB as this has been known to cause issues with client connectivity. Configure DNS with a hostname and either an A record or CNAME record to your static IPv4 address. <Note>By convention, it is reccommended that hostnames for nodes in mainnet be defined on a per operator address basis with a subdomain using an airport code prefix distinct from other node operators as in `<airport-code>-<node_number>.<domain>`. See [mainnet node list](https://haneda-1.nodes.towns-u4.com/debug/multi) for additional examples of the convention. </Note> <Warning> Application level load balancers (ALBs) require a very specific configuration to handle gRPC traffic as well as ALPN with HTTP1/2 and therefore are not supported at this time. Terminate TLS at your origin server and use a static IPv4 address for your Node FE. Network load balancers are supported assuming 1 LB instance per origin. </Warning> </Step> <Step title="Node Storage Setup"> Set up Node Storage (e.g., Postgres), ensuring your Node FE can connect within your hosting network. Run network probes on the Node FE in [info mode](https://github.com/towns-protocol/towns/tree/main/core/node#checking-on-gamma-status-from-local-host) to ensure network connectivity, TLS termination, and that the node is publicly addressable over DNS. </Step> </Steps> # System Requirements & Installation Source: https://docs.towns.com/node-operator/tutorials/system-requirements-installation The following guide describes system requirements, dependencies, and installation details recommended for running a Towns Stream Node. This guide applies to nodes running in either Testnet or Mainnet. <Note>By adhering to the guidelines outlined in this guide, node operators can contribute to the stability and efficiency of the Towns Network. Effective node operation not only benefits the individual operator by ensuring optimal node performance but also supports the health and reliability of the entire network.</Note> <br /> ### System Requirements & Dependencies To run a Towns Stream Node, an operator will need to run a Node Frontend (FE) and Node Storage layer, postgres database, with a specific network configuration. Please read the below requirements carefully prior to proceeding with node setup. <Accordion title="Node Frontend (FE) Requirements"> * **CPU**: Minimum 8 virtual CPUs. * **Memory**: At least 32 GB of RAM. - **Architecture**: x64 or ARM64 supported. * **Network**: Dedicated, static public IP address, capable of handling up to 1 Gbps ingress and egress for HTTP 1.1/2 traffic. * **Blockchain RPC Access**: Access to blockchain RPC provider endpoints for Base Chain, Towns Chain, and cross-chain chain ids. </Accordion> <Accordion title="Node Storage Requirements"> * **Database Compatibility**: Postgres 15.4 or newer. * **Transaction Processing**: Capable of handling up to 10k IOps. * **Storage Capacity**: Minimum 2 TB of storage. * **Keypair store**: Location to store ECDSA keypair associated with the data stored in the database. <Note>It is highly recommended to run a distinct Postgres instance for each Node FE to ensure resource isolation during upgrades.</Note> </Accordion> <Accordion title="Node Eth Balance Requirements"> * **Towns Chain Eth Balance**: Minimum 1 ETH on all stream node wallets in Towns Chain to support gas needed for miniblock validation. * **Base Chain Eth Balance**: Minimum 0.5 ETH on all stream node wallets in Base Chain to support gas needed for cross-chain entitlement checks. <Note>Set up alerts to monitor the balance of the node's Eth balance on Towns Chain and Base Chain at a minimum alert threshold of 0.25 ETH and 0.1 ETH respectively.</Note> </Accordion> <br /> ### Installation Node FE's can be installed either from docker with the Towns public [ECR image registry](https://public.ecr.aws/h5v6m2x1/river) or built from [source code](https://github.com/towns-protocol/towns/tree/main/core/node). #### Installation from Docker <Accordion title="Install Image from Towns Public Image Registry"> The Towns Protocol maintains a public docker image registry `public.ecr.aws/h5v6m2x1/river` for images that are built officially from [source](https://github.com/towns-protocol/towns) during CI/CD. As such, node operators can easily install the latest Node FE software from images stored in the public ECR registry. Images are tagged during [releases](/node-operator/release-process) with the associated commit as well as mutable tags `mainnet`, `testnet`, for each network respectively. ```bash theme={null} docker pull public.ecr.aws/h5v6m2x1/river:testnet docker tag public.ecr.aws/h5v6m2x1/river:testnet river-node ``` <Note>Images are tagged by their merge commit hash so to install a specific version of the Node FE software, use the commit hash from source instead of the `testnet` or `mainnet` tag, which references the latest built image.</Note> ```bash theme={null} git clone git@github.com:towns-protocol/towns.git # print out shorthand commit hashes git log --pretty=format:'%h' | cut -c 1-7 # choose one to pull COMMIT_HASH=1dd452a docker pull public.ecr.aws/h5v6m2x1/river:$COMMIT_HASH ``` <Info> The CI job that builds docker images to the river public ecr registry can be found [here](https://github.com/towns-protocol/towns/blob/main/.github/workflows/River_node_docker.yml). </Info> </Accordion> <Accordion title="Build Docker Image from Source"> As of October 2024, as an alternative to the public ECR registry, it is recommended to build the docker image from the source [Dockerfile](https://github.com/towns-protocol/towns/blob/main/core/Dockerfile) to ensure compatibility with the latest software version. ```bash theme={null} git clone git@github.com:towns-protocol/towns.git cd river/core docker build -t river-node . ``` </Accordion> <br /> ### Node FE Environment Variables Towns Stream Nodes run expecting certain environment variables to be present in the process environment and set at runtime. Config, which is described in [config.go](https://github.com/towns-protocol/towns/blob/main/core/config/config.go), is injected into the binary at runtime using [viper](https://github.com/spf13/viper). <Note>For the list of contracts required to run nodes and their addresses, see [contracts](/node-operator/contracts). </Note> <br /> | Environment Variable | Purpose | Required | Testnet Value | Secret | | ------------------------------------------- | -------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------ | ------ | | ARCHITECTCONTRACT\_\_ADDRESS | SpaceFactory contract address in Base Network | Yes | 0x5A077e686545c541476D3a99711dE42339357467 | - | | ARCHITECTCONTRACT\_\_VERSION | Contract interface version | Yes | v3 | - | | BASECHAIN\_\_CHAINID | Base ChainId | Yes | 84532 | - | | BASECHAIN\_\_NETWORKURL | Base Chain RPC Url | Yes | [https://sepolia.base.org](https://sepolia.base.org) | Yes | | CHAINSSTRING | List of chainIds and network RPC Urls supported | Yes | see [Cross-chain Requirements](/node-operator/tutorials/system-requirements-installation#cross-chain-requirements) | - | | DATABASE\_\_DATABASE | Postgres DB Name | Yes | river | - | | DATABASE\_\_EXTRA | Extra Postgres Options | Yes | ?sslmode=disable\&pool\_max\_conns=1000 | - | | DATABASE\_\_HOST | Postgres DB Host Url | Yes | - | - | | DATABASE\_\_PASSWORD | Postgres DB Password | Yes | - | Yes | | DATABASE\_\_PORT | Postgres DB port | Yes | 5432 | - | | DATABASE\_\_USER | Postgres DB username | Yes | - | - | | DD\_TAGS | Used by Datadog for metrics collection | No | env: (gamma), node\_url:(your complete node url) | No | | DEBUGENDPOINTS\_\_PPROF | Enable pprof endpoints | No | false | - | | DEBUGENDPOINTS\_\_PRIVATEDEBUGSERVERADDRESS | Private debug server address | No | :8080 | - | | DEBUGENDPOINTS\_\_MEMPROFILEDIR | Directory for memory profile files | No | ./mem\_profile | - | | ENTITLEMENT\_CONTRACT\_\_ADDRESS | Entitlement contract address in Base Network | Yes | 0x0d7eC5826626070b6a250C9878940D070128A265 | - | | LOG\_\_FORMAT | Log format option | No | text | - | | LOG\_\_LEVEL | Default log level | No | info | - | | LOG\_\_NOCOLOR | Logging without color | No | true | - | | METRICS\_\_ENABLED | Metrics exporter enabled | No | true | - | | METRICS\_\_PORT | Metrics export port | No | 8081 | - | | PERFORMANCETRACKING\_\_PROFILINGENABLED | Used by Datadog for cpu profiling | no | true | No | | PERFORMANCETRACKING\_\_TRACINGENABLED | Used by Datadog for tracing | no | true | No | | PORT | Port RPC service listens on | Yes | 443 | - | | REGISTRYCONTRACT\_\_ADDRESS | River Registry contract address in Towns Chain Network | Yes | 0x94bdc7016057fc47cC006Bc837bF0Aed5Dc5C6D6 | - | | RIVERCHAIN\_\_CHAINID | Towns Chain chainId | Yes | 6524490 | - | | RIVERCHAIN\_\_NETWORKURL | Towns Chain RPC Url | Yes | [https://testnet.rpc.towns.com/http](https://testnet.rpc.towns.com/http) | Yes | | RUN\_MODE | Stream Node Run Mode (full, archive) | No | full | - | | SKIP\_GENKEY | Skip generating node ECDSA wallet keypair | Yes | true | - | | STANDBYONSTART | Start node in standby mode | No | false | - | | STORAGE\_TYPE | postgres or in-memory | No | postgres | - | | TLSCONFIG\_\_CERT | TLS certificate value for node hostname | Yes | - | Yes | | TLSCONFIG\_\_KEY | TLS certificate key for nod
프로젝트로 돌아가기