aelf 백서

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

r for the creation request to succeed, some assertions must pass: The Sender can only have one pending request at any time. The locked_token_amount cannot be lower than the indexing price. If is_privilege_preserved is true (exclusive side chain), the token initial issue list cannot be empty and all with an amount greater than 0. If is_privilege_preserved is true (exclusive side chain), the initial_resource_amount must contain all resource tokens of the chain, and the value must be greater than 0. The allowance approved to cross-chain contract from the proposer (Sender of the transaction) cannot be lower than the locked_token_amount . No need to provide data about side chain token if is_privilege_preserved is false. var sideChainCreationRequest = async function ( crossChainContract ) { // call the cross-chain contract to request the creation const creationRequestResult = await crossChainContract . RequestSideChainCreation ( { indexing_price : 1 , locked_token_amount : 20000 , is_privilege_preserved : true , side_chain_token_creation_request : { side_chain_token_symbol : "MEGA" , side_chain_token_name : "MEGA" , side_chain_token_total_supply : 100000000 , side_chain_token_decimals : 8 , } , side_chain_token_initial_issue_list : [ { address : defaultPrivateKeyAddress , amount : 10000000 , } , ] , initial_resource_amount : { CPU : 100 , RAM : 100 , DISK : 100 , NET : 100 , } , } ) ; let sideChainProposalResult = await pollMining ( creationRequestResult . TransactionId ) ; let logs = parseLogs ( sideChainProposalResult . Logs ) ; let proposalId = logs . ProposalId ; } ; The cross-chain contract emits an event containing the ProposalId . This is needed for the last step. Approve the Proposal ​ This is where the parliament organization members approve the proposal: var proposalApproveTx = await parliamentContract . Approve ( deserializedLogs [ 0 ] . proposalId ) ; await pollMining ( proposalApproveTx . TransactionId ) ; Note : when calling Approve it will be the Sender of the transaction that approves. Here the script is set to use the key of one parliament organization member, see full script at the end. Release the Proposal ​ This part of the script releases the proposal: var releaseResult = await crossChainContract . ReleaseSideChainCreation ( { proposalId : deserializedLogs [ 0 ] . proposalId } ) ; let releaseTxResult = await pollMining ( releaseResult . TransactionId ) ; // Parse the logs to get the chain id. let sideChainCreationEvent = crossChainContract . deserializeLog ( releaseTxResult . Logs , 'SideChainCreatedEvent' ) ; This is the last step involved in creating a side chain, after this the chain id of the new side chain is accessible in the SideChainCreatedEvent event log. Complete Script ​ This script demonstrates the essential steps to create a side chain in the aelf ecosystem. The developer must approve some ELF tokens, request the side chain creation, get approval from the parliament organization, and finally release the proposal to create the side chain. Ensure to set the proper configurations and values as per your blockchain environment. const AElf = require ( "aelf-sdk" ) ; const Wallet = AElf . wallet ; const { sha256 } = AElf . utils ; // set the private key of the block producer const defaultPrivateKey = "e119487fea0658badc42f089fbaa56de23d8c0e8d999c5f76ac12ad8ae897d76" ; const defaultPrivateKeyAddress = "HEtBQStfqu53cHVC3PxJU6iGP3RGxiNUfQGvAPTjfrF3ZWH3U" ; const wallet = Wallet . getWalletByPrivateKey ( defaultPrivateKey ) ; // link to the node const aelf = new AElf ( new AElf . providers . HttpProvider ( "http://127.0.0.1:8000" ) ) ; if ( ! aelf . isConnected ( ) ) { console . log ( "Could not connect to the node." ) ; } const tokenContractName = "AElf.ContractNames.Token" ; const parliamentContractName = "AElf.ContractNames.Parliament" ; const crossChainContractName = "AElf.ContractNames.CrossChain" ; var pollMining = async function ( transactionId ) { console . log ( ` >> Waiting for ${ transactionId } the transaction to be mined. ` ) ; for ( i = 0 ; i < 10 ; i ++ ) { const currentResult = await aelf . chain . getTxResult ( transactionId ) ; // console.log('transaction status: ' + currentResult.Status); if ( currentResult . Status === "MINED" ) return currentResult ; await new Promise ( ( resolve ) => setTimeout ( resolve , 2000 ) ) . catch ( function ( ) { console . log ( "Promise Rejected" ) ; } ) ; } } ; var setAllowance = async function ( tokenContract , crossChainContractAddress ) { console . log ( "\n>>>> Setting allowance for the cross-chain contract." ) ; // set some allowance to the cross-chain contract const approvalResult = await tokenContract . Approve ( { symbol : "ELF" , spender : crossChainContractAddress , amount : 20000 , } ) ; await pollMining ( approvalResult . TransactionId ) ; } ; var checkAllowance = async function ( tokenContract , owner , spender ) { console . log ( "\n>>>> Checking the cross-chain contract's allowance" ) ; const checkAllowanceTx = await tokenContract . GetAllowance . call ( { symbol : "ELF" , owner : owner , spender : spender , } ) ; console . log ( ` >> allowance to the cross-chain contract: ${ checkAllowanceTx . allowance } ${ checkAllowanceTx . symbol } ` ) ; } ; const createSideChain = async ( ) => { // get the status of the chain in order to get the genesis contract address console . log ( "Starting side chain creation script\n" ) ; const chainStatus = await aelf . chain . getChainStatus ( { sync : true } ) ; const genesisContract = await aelf . chain . contractAt ( chainStatus . GenesisContractAddress , wallet ) . catch ( ( err ) => { console . log ( err ) ; } ) ; // get the addresses of the contracts that we'll need to call const tokenContractAddress = await genesisContract . GetContractAddressByName . call ( sha256 ( tokenContractName ) ) ; const parliamentContractAddress = await genesisContract . GetContractAddressByName . call ( sha256 ( parliamentContractName ) ) ; const crossChainContractAddress = await genesisContract . GetContractAddressByName . call ( sha256 ( crossChainContractName ) ) ; // build the aelf-sdk contract object const parliamentContract = await aelf . chain . contractAt ( parliamentContractAddress , wallet ) ; const tokenContract = await aelf . chain . contractAt ( tokenContractAddress , wallet ) ; const crossChainContract = await aelf . chain . contractAt ( crossChainContractAddress , wallet ) ; // 1. set and check the allowance, spender is the cross-chain contract await setAllowance ( tokenContract , crossChainContractAddress ) ; await checkAllowance ( tokenContract , defaultPrivateKeyAddress , crossChainContractAddress ) ; // 2. request the creation of the side chain with the cross=chain contract console . log ( "\n>>>> Requesting the side chain creation." ) ; const sideChainCreationRequestTx = await crossChainContract . RequestSideChainCreation ( { indexingPrice : 1 , lockedTokenAmount : "20000" , isPrivilegePreserved : true , sideChainTokenCreationRequest : { sideChainTokenDecimals : 8 , sideChainTokenName : "SCATokenName" , sideChainTokenSymbol : "SCA" , sideChainTokenTotalSupply : "100000000000000000" , } , sideChainTokenInitialIssueList : [ { address : "28Y8JA1i2cN6oHvdv7EraXJr9a1gY6D1PpJXw9QtRMRwKcBQMK" , amount : "1000000000000000" , } , ] , initialResourceAmount : { CPU : 2 , RAM : 4 , DISK : 512 , NET : 1024 } , } ) ; let sideChainCreationRequestTxResult = await pollMining ( sideChainCreationRequestTx . TransactionId ) ; // deserialize the log to get the proposal's ID. let deserializedLogs = parliamentContract . deserializeLog ( sideChainCreationRequestTxResult . Logs , "ProposalCreated" ) ; console . log ( ` >> side chain creation request proposal id ${ JSON . stringify ( deserializedLogs [ 0 ] . proposalId ) } ` ) ; // 3. Approve the proposal console . log ( "\n>>>> Approving the proposal." ) ; var proposalApproveTx = await parliamentContract . Approve ( deserializedLogs [ 0 ] . proposalId ) ; await pollMining ( proposalApproveTx . TransactionId ) ; // 3. Release the side chain console . log ( "\n>>>> Release the side chain." ) ; var releaseResult = await crossChainContract . ReleaseSideChainCreation ( { proposalId : deserializedLogs [ 0 ] . proposalId , } ) ; let releaseTxResult = await pollMining ( releaseResult . TransactionId ) ; // Parse the logs to get the chain id. let sideChainCreationEvent = crossChainContract . deserializeLog ( releaseTxResult . Logs , "SideChainCreatedEvent" ) ; console . log ( "Chain chain created : " ) ; console . log ( sideChainCreationEvent ) ; } ; createSideChain ( ) . then ( ( ) => { console . log ( "Done." ) ; } ) ; Note : Replace the placeholders in the script with actual values and logic for your use case. Running a Side Chain ​ Description : A tutorial on how to configure and run a side chain node in the aelf blockchain ecosystem after its creation has been approved. Purpose : To guide developers through the setup and launch process of a side chain node, ensuring correct configuration and successful integration with the main chain. This tutorial explains how to run a side chain node after it has been approved by the producers and released by the creator. After creating the side chain, producers need to run a side chain node. Prerequisites ​ You already have a main-chain node running. The creation of the side chain has been approved and released. Important Note ​ The key-pair (account) used for mining on the side chain must be the same as the one used on the main-chain node. Both production nodes need to be launched with the same key-pair. Side Chain Configuration ​ Configuration Files ​ Two configuration files must be placed in the configuration folder of the side chain, from which you will launch the node: appsettings.json appsettings.SideChain.MainNet.json Chain ID and Settings ​ After the release of the side chain creation request, the ChainId of the new side chain will be accessible in the SideChainCreatedEvent logged by the transaction that released it. In this example, we will set up the side chain node with ChainId tDVV (1866392 converted to base58), connecting to Redis db2 , and using web API port 1235 . Don’t forget to change the account , password , and initial miner . appsettings.json { "ChainId" : "tDVV" , "ChainType" : "SideChain" , "NetType" : "MainNet" , "ConnectionStrings" : { "BlockchainDb" : "redis://localhost:6379?db=2" , "StateDb" : "redis://localhost:6379?db=2" } , "Account" : { "NodeAccount" : "YOUR PRODUCER ACCOUNT" , "NodeAccountPassword" : "YOUR PRODUCER PASSWORD" } , "Kestrel" : { "EndPoints" : { "Http" : { "Url" : "http://*:1235/" } } } , "Consensus" : { "MiningInterval" : 4000 , "StartTimestamp" : 0 } } appsettings.SideChain.MainNet.json { "CrossChain" : { "Grpc" : { "ParentChainServerPort" : 5010 , "ListeningPort" : 5000 , "ParentChainServerIp" : "127.0.0.1" } , "ParentChainId" : "AELF" } } Change ParentChainServerIp and ParentChainServerPort depending on the listening address of your mainchain node. Launching the Side Chain Node ​ Open a terminal and navigate to the folder where you created the side chain configuration: Terminal dotnet .. /AElf.Launcher.dll You can try out a few commands from another terminal to check if everything is fine, for example: Terminal aelf-command get-blk-height -e http://127.0.0.1:1235 Side Chain Creation API API for Proposing Side Chain Creation Side Chain Types Paying for Side Chain Indexing Fee Resource Fee Simple Demo for Side Chain Creation Request Step-by-Step Code Snippets Set-Up Creation of the Side Chain Complete Script Running a Side Chain Prerequisites Important Note Side Chain Configuration Launching the Side Chain Node ## /quick-start/node-operators/run-aelf-on-cloud On this page This guide will walk you through the steps required to run an aelf node on Google Cloud Platform (GCP). Step 1: Launch aelf Image ​ Go to the Google Cloud Marketplace and search for "aelf blockchain for enterprise". Find the aelf image and click on "LAUNCH ON COMPUTE ENGINE". Keep the default settings and click "DEPLOY" at the bottom left of the page. Step 2: Access and Start the Chain ​ Login to the launched VM instance via SSH. You can do this by clicking the SSH drop-down and selecting "Open in browser window". In the SSH session, execute sudo bash to elevate your privileges. Start the chain with one of the following commands: Run it in the foreground: cd /opt/aelf-node && docker-compose up Or run it in the background: cd /opt/aelf-node && docker-compose up -d Step 3: Verify Chain Status ​ To verify that the node is working, use the following command to send an HTTP request and get the current chain status: curl -X GET "http://127.0.0.1:8001/api/blockChain/chainStatus" -H "accept: text/plain; v=1.0" If everything is working normally, you should see the chain status increase with each request. Step 1: Launch aelf Image Step 2: Access and Start the Chain Step 3: Verify Chain Status ## /learn/core 📄️ Core Introduction Overview of aelf, its architecture, and key features. 📄️ Core Implementation Design Principles ## /learn/cross-chain 📄️ Introduction aelf's cross-chain functionalities 📄️ Architecture aelf's cross-chain system architecture 📄️ Cross Chain Verification aelf's cross-chain verification process 📄️ Verify Verification methods for aelf cross-chain 📄️ Cross Chain Transfer Performing cross-chain transfers in aelf ## /learn/consensus On this page Consensus Overview ​ Consensus is crucial for blockchains as it decides which transactions are included in the block and their order. aelf's block formation mechanism is more complex than Bitcoin and Ethereum due to its need to record Side Chain data and its cloud-based service design. Miners must update info from multiple parallel Chains. aelf uses AEDPoS consensus for high-frequency and predictable block formation. How aelf Consensus Works: ​ Election : Determines who gets to produce blocks. Scheduling : Decides when those blocks are produced. Core Data Center ​ Core Data Centers, also known as Miners or Block Producers, act like parliament members in the aelf blockchain. aelf has 2N+1 Core Data Centers, starting with 8 and increasing by 1 each year. These nodes enforce aelf’s consensus rules, relay transactions, confirm transactions, package blocks, and transfer data. They also act as miners for some Side Chains and are elected by ELF token holders. Validate Data Center ​ Anyone can join the election by locking ELF tokens. The top (2N+1)*5 nodes become Validate Data Centers, with N starting at 8 and increasing by 1 each year. AEDPoS Process ​ Round ​ aelf operates in units called "rounds." In each round, one Core Data Center produces one block and has one extra transaction at the end. Main Processes ​ Pre-Verification ​ Before generating blocks in round (t+1), a node’s status in round t is verified by checking hash(in_node(t)) = out_node(t) . Order Calculation ​ In each round, Core Data Centers have (N+1) block generation time slots. The order and signature for each node in the first round are arbitrary. From the second round, the signature is calculated using sig_node(t+1) = hash(in_node(t) + all_t) where Here node[i][t], means the node is processing the i-th transaction in round t. From round 3, the order is based on the previous round’s order and signature. In round (t+1), we traverse the signature of nodes at round t in order. The ordering of a node in (t+1) is calculated by If conflicts occur, the node is assigned to the next available place. The extra transaction node is calculated from the first place node's signature of the previous round. Timing ​ Nodes have 4 seconds to process transactions. Failure to submit within this time results in a penalty. If a node fails twice consecutively, it enters a penalty period, increasing exponentially with each failure. Fork Handling ​ Only one node generates blocks at a time to avoid forks. If multiple orphan nodes occur, the longest chain is adopted. Vicious nodes mining in two chains are voted out. Irreversible Block ​ Some block links (block height to hash value) are irreversible, confirmed by the AEDPoS mechanism during round changes. Overview Core Data Center Validate Data Center AEDPoS Process Round Main Processes Irreversible Block ## /learn/network On this page Network Introduction ​ The network layer in aelf is vital for maintaining connections and communication between nodes. It supports higher-level logic like synchronization and allows node operators to monitor and manage network operations. aelf uses gRPC for connections to keep the design simple and flexible. Architecture ​ The network consists of three layers: aelf.OS Handles network events. Runs background tasks for network operations. aelf.OS.Core.Network Provides services to higher levels. Defines infrastructure components and types. aelf.OS.Network.Grpc Implements the infrastructure layer using gRPC. Manages low-level functions like serialization and retrying. aelf.OS ​ This layer monitors and handles network-related events: Transaction Accepted Event : When a transaction is verified. Block Mined Event : When a block is packaged. Block Accepted Event : When a block is executed successfully. New Irreversible Block Found Event : When a new irreversible block is found. It also performs regular tasks: Peer Health Check : Ensures connected peers are healthy. Peer Retry Connection : Attempts to reconnect with unhealthy peers. Network Node Discovery : Finds new nodes. aelf.OS.Core.Network ​ This core module includes: NetworkService : Manages sending/receiving requests, broadcasting items to peers, and handling network exceptions. IPeerPool/PeerPool : Manages active peer connections. IPeer : Defines peer interactions and metrics. IaelfNetworkServer : Manages network lifecycle and connections. aelf.OS.Network.Grpc ​ Implements the infrastructure layer using gRPC: GrpcPeer : Implements IPeer . GrpcStreamPeer : Client-side IPeer implementation (node version >=1.4.0). GrpcStreamBackPeer : Server-side IPeer implementation (node version >=1.4.0). GrpcNetworkServer : Implements IaelfNetworkServer . GrpcServerService : Manages network service interfaces and data exchange. Extra functionalities include: Serializing and deserializing requests. Implementing request/response mechanisms. Authentication. Protocol ​ Nodes use a defined network interface protocol for normal operation and data synchronization. Connection ​ DoHandshake ​ When a node connects, it exchanges handshake information. This includes chain status, current height, and more. Request : rpc DoHandshake ( HandshakeRequest ) returns ( HandshakeReply ) { } Handshake Message : message Handshake { HandshakeData handshake_data = 1 ; bytes signature = 2 ; bytes session_id = 3 ; } HandshakeData Message : message HandshakeData { int32 chain_id = 1 ; int32 version = 2 ; int32 listening_port = 3 ; bytes pubkey = 4 ; aelf . Hash best_chain_hash = 5 ; int64 best_chain_height = 6 ; aelf . Hash last_irreversible_block_hash = 7 ; int64 last_irreversible_block_height = 8 ; google . protobuf . Timestamp time = 9 ; } ConfirmHandshake ​ Confirms the handshake with the target node. Request : rpc ConfirmHandshake ( ConfirmHandshakeRequest ) returns ( VoidReply ) { } Broadcasting ​ BlockBroadcastStream ​ Receives bloc
프로젝트로 돌아가기