forked from cerc-io/stack-orchestrator
		
	Lotus stack usability improvements (#489)
* move health check inside startup script * remove pre-built genesis * move health check inside startup script * remove pre-built genesis * Use hardcoded paths for Lotus node data directories * Persist proof parameters * Write out miner node's multiaddr with docker network IP * Enable Lotus ETH RPC API and bind to all available interfaces * Fund a known account --------- Co-authored-by: iskay <ikay@lakeheadu.ca> Co-authored-by: Ian Kay <ian@knowable.vc>
This commit is contained in:
		
							parent
							
								
									dc7bc6af31
								
							
						
					
					
						commit
						333797b0c3
					
				| @ -8,17 +8,9 @@ services: | ||||
|     image: cerc/lotus:local | ||||
|     volumes: | ||||
|       - ../config/fixturenet-lotus/setup-miner.sh:/docker-entrypoint-scripts.d/setup-miner.sh | ||||
|       - ../config/fixturenet-lotus/genesis/devgen.car:/devgen.car | ||||
|       - $HOME/stack-orchestrator/app/data/config/fixturenet-lotus/genesis/.genesis-sectors:/root/.genesis-sectors | ||||
|       - ../config/fixturenet-lotus/fund-account.sh:/fund-account.sh | ||||
|       - lotus_miner_params:/var/tmp/filecoin-proof-parameters | ||||
|       - lotus-shared:/root/.lotus-shared | ||||
|     healthcheck: | ||||
| #      test: ["CMD-SHELL", "grep 'started ChainNotify channel' /var/log/lotus.log"] | ||||
| #      test: ["CMD-SHELL", "[ -f /root/.lotus-shared/miner.addr ]"] | ||||
|       test: ["CMD-SHELL", "[ -d /root/.lotus-miner-local-net ]"] | ||||
|       interval: 10s | ||||
|       timeout: 10s | ||||
|       retries: 10 | ||||
|       start_period: 60s | ||||
|     entrypoint: ["sh", "/docker-entrypoint-scripts.d/setup-miner.sh"] | ||||
|     ports: | ||||
|       - "1234" | ||||
| @ -30,14 +22,16 @@ services: | ||||
|     hostname: lotus-node-1 | ||||
|     env_file: | ||||
|       - ../config/fixturenet-lotus/lotus-env.env | ||||
|     environment: | ||||
|       # Use 0.0.0.0 so that calls can be made from outside the container | ||||
|       - LOTUS_API_LISTENADDRESS=/ip4/0.0.0.0/tcp/1234/http | ||||
|     image: cerc/lotus:local | ||||
|     volumes: | ||||
|       - ../config/fixturenet-lotus/setup-node.sh:/docker-entrypoint-scripts.d/setup-node.sh | ||||
|       - ../config/fixturenet-lotus/genesis/devgen.car:/devgen.car | ||||
|       - lotus_node_1_params:/var/tmp/filecoin-proof-parameters | ||||
|       - lotus-shared:/root/.lotus-shared | ||||
|     depends_on: | ||||
|       lotus-miner: | ||||
|         condition: service_healthy | ||||
|       - lotus-miner | ||||
|     entrypoint: ["sh", "/docker-entrypoint-scripts.d/setup-node.sh"] | ||||
|     ports: | ||||
|       - "1234" | ||||
| @ -49,14 +43,16 @@ services: | ||||
|     hostname: lotus-node-2 | ||||
|     env_file: | ||||
|       - ../config/fixturenet-lotus/lotus-env.env | ||||
|     environment: | ||||
|       # Use 0.0.0.0 so that calls can be made from outside the container | ||||
|       - LOTUS_API_LISTENADDRESS=/ip4/0.0.0.0/tcp/1234/http | ||||
|     image: cerc/lotus:local | ||||
|     volumes: | ||||
|       - ../config/fixturenet-lotus/setup-node.sh:/docker-entrypoint-scripts.d/setup-node.sh | ||||
|       - ../config/fixturenet-lotus/genesis/devgen.car:/devgen.car | ||||
|       - lotus_node_2_params:/var/tmp/filecoin-proof-parameters | ||||
|       - lotus-shared:/root/.lotus-shared | ||||
|     depends_on: | ||||
|       lotus-miner: | ||||
|         condition: service_healthy | ||||
|       - lotus-miner | ||||
|     entrypoint: ["sh", "/docker-entrypoint-scripts.d/setup-node.sh"] | ||||
|     ports: | ||||
|       - "1234" | ||||
| @ -65,4 +61,7 @@ services: | ||||
|       - "1777" | ||||
| 
 | ||||
| volumes: | ||||
|   lotus-shared: | ||||
|   lotus_miner_params: | ||||
|   lotus_node_1_params: | ||||
|   lotus_node_2_params: | ||||
|   lotus-shared: | ||||
|  | ||||
							
								
								
									
										20
									
								
								app/data/config/fixturenet-lotus/fund-account.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										20
									
								
								app/data/config/fixturenet-lotus/fund-account.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,20 @@ | ||||
| #!/bin/bash | ||||
| 
 | ||||
| # ETH account with pk c05fd3613bcd62a4f25e5eba1f464d0b76d74c3f771a7c2f13e26ad6439444b3 | ||||
| ETH_ADDRESS=0xD375B03bd3A2434A9f675bEC4Ccd68aC5e67C743 | ||||
| AMOUNT=1000 | ||||
| 
 | ||||
| # Pre-fund stat | ||||
| PREFUND_STAT_OUTPUT=$(lotus evm stat $ETH_ADDRESS) | ||||
| 
 | ||||
| FILECOIN_ADDRESS=$(echo "$PREFUND_STAT_OUTPUT" | grep -oP 'Filecoin address:\s+\K\S+') | ||||
| echo Filecoin address: "$FILECOIN_ADDRESS" | ||||
| 
 | ||||
| echo Sending balance to "$FILECOIN_ADDRESS" | ||||
| lotus send --from $(lotus wallet default) "$FILECOIN_ADDRESS" $AMOUNT | ||||
| 
 | ||||
| # Post-fund stat | ||||
| echo lotus evm stat $ETH_ADDRESS | ||||
| lotus evm stat $ETH_ADDRESS | ||||
| 
 | ||||
| echo "Account with ETH address $ETH_ADDRESS funded" | ||||
| @ -1 +0,0 @@ | ||||
| }+V<>{iνΆΠΉ<CEA0>²<EFBFBD>¨ΣΗ\k»qς
—?δΪAΒfκ’~μ©™LΉ<4C>tb·yqτ·²ηξΔ<CEBE>Ο?ξaΣ<61>J | ||||
| @ -1 +0,0 @@ | ||||
| Βfκ’~μ©™LΉ<4C>tb·yqτ·²ηξΔ<CEBE>Ο?ξaΣ<61>J | ||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -1,71 +0,0 @@ | ||||
| { | ||||
|   "t01000": { | ||||
|     "ID": "t01000", | ||||
|     "Owner": "t3spusn5ia57qezc3fwpe3n2lhb4y4xt67xoflqbqy2muliparw2uktevletuv7gl4qakjpafgcl7jk2s2er3q", | ||||
|     "Worker": "t3spusn5ia57qezc3fwpe3n2lhb4y4xt67xoflqbqy2muliparw2uktevletuv7gl4qakjpafgcl7jk2s2er3q", | ||||
|     "PeerId": "12D3KooWG5q6pWJVdPBhDBv9AjWVbUh4xxTAZ7xvgZSjczWuD2Z9", | ||||
|     "MarketBalance": "0", | ||||
|     "PowerBalance": "0", | ||||
|     "SectorSize": 2048, | ||||
|     "Sectors": [ | ||||
|       { | ||||
|         "CommR": { | ||||
|           "/": "bagboea4b5abcboxypcewlkmrat2myu4vthk3ii2pcomak7nhqmdbb6sxlolp2wdf" | ||||
|         }, | ||||
|         "CommD": { | ||||
|           "/": "baga6ea4seaqn3jfixthmdgksv4vhfeuyvr6upw6tvaqbmzmsyxnzosm4pwgnmlq" | ||||
|         }, | ||||
|         "SectorID": 0, | ||||
|         "Deal": { | ||||
|           "PieceCID": { | ||||
|             "/": "baga6ea4seaqn3jfixthmdgksv4vhfeuyvr6upw6tvaqbmzmsyxnzosm4pwgnmlq" | ||||
|           }, | ||||
|           "PieceSize": 2048, | ||||
|           "VerifiedDeal": false, | ||||
|           "Client": "t3spusn5ia57qezc3fwpe3n2lhb4y4xt67xoflqbqy2muliparw2uktevletuv7gl4qakjpafgcl7jk2s2er3q", | ||||
|           "Provider": "t01000", | ||||
|           "Label": "0", | ||||
|           "StartEpoch": 0, | ||||
|           "EndEpoch": 9001, | ||||
|           "StoragePricePerEpoch": "0", | ||||
|           "ProviderCollateral": "0", | ||||
|           "ClientCollateral": "0" | ||||
|         }, | ||||
|         "DealClientKey": { | ||||
|           "Type": "bls", | ||||
|           "PrivateKey": "tFvSRiSg2G3Ssgg0PSYy23XyjaIMXpsmdyG2B7UFLT4=" | ||||
|         }, | ||||
|         "ProofType": 5 | ||||
|       }, | ||||
|       { | ||||
|         "CommR": { | ||||
|           "/": "bagboea4b5abcb6krzypqcczhcnbeyjcqkeo6omfergm336o3kitugh3jgjog2yqq" | ||||
|         }, | ||||
|         "CommD": { | ||||
|           "/": "baga6ea4seaqhondpb2373hjasjplxvbjzi5n5mm4fbbhjxp5ptnbq4cibapkeii" | ||||
|         }, | ||||
|         "SectorID": 1, | ||||
|         "Deal": { | ||||
|           "PieceCID": { | ||||
|             "/": "baga6ea4seaqhondpb2373hjasjplxvbjzi5n5mm4fbbhjxp5ptnbq4cibapkeii" | ||||
|           }, | ||||
|           "PieceSize": 2048, | ||||
|           "VerifiedDeal": false, | ||||
|           "Client": "t3spusn5ia57qezc3fwpe3n2lhb4y4xt67xoflqbqy2muliparw2uktevletuv7gl4qakjpafgcl7jk2s2er3q", | ||||
|           "Provider": "t01000", | ||||
|           "Label": "1", | ||||
|           "StartEpoch": 0, | ||||
|           "EndEpoch": 9001, | ||||
|           "StoragePricePerEpoch": "0", | ||||
|           "ProviderCollateral": "0", | ||||
|           "ClientCollateral": "0" | ||||
|         }, | ||||
|         "DealClientKey": { | ||||
|           "Type": "bls", | ||||
|           "PrivateKey": "tFvSRiSg2G3Ssgg0PSYy23XyjaIMXpsmdyG2B7UFLT4=" | ||||
|         }, | ||||
|         "ProofType": 5 | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
| } | ||||
| @ -1 +0,0 @@ | ||||
| 7b2254797065223a22626c73222c22507269766174654b6579223a227446765352695367324733537367673050535979323358796a61494d5870736d64794732423755464c54343d227d | ||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -1,11 +0,0 @@ | ||||
| { | ||||
|   "ID": "f355523e-69d0-4984-bd0e-9588487c6231", | ||||
|   "Weight": 0, | ||||
|   "CanSeal": false, | ||||
|   "CanStore": false, | ||||
|   "MaxStorage": 0, | ||||
|   "Groups": null, | ||||
|   "AllowTo": null, | ||||
|   "AllowTypes": null, | ||||
|   "DenyTypes": null | ||||
| } | ||||
										
											Binary file not shown.
										
									
								
							| @ -1,108 +0,0 @@ | ||||
| { | ||||
|   "NetworkVersion": 18, | ||||
|   "Accounts": [ | ||||
|     { | ||||
|       "Type": "account", | ||||
|       "Balance": "50000000000000000000000000", | ||||
|       "Meta": { | ||||
|         "Owner": "t3spusn5ia57qezc3fwpe3n2lhb4y4xt67xoflqbqy2muliparw2uktevletuv7gl4qakjpafgcl7jk2s2er3q" | ||||
|       } | ||||
|     } | ||||
|   ], | ||||
|   "Miners": [ | ||||
|     { | ||||
|       "ID": "t01000", | ||||
|       "Owner": "t3spusn5ia57qezc3fwpe3n2lhb4y4xt67xoflqbqy2muliparw2uktevletuv7gl4qakjpafgcl7jk2s2er3q", | ||||
|       "Worker": "t3spusn5ia57qezc3fwpe3n2lhb4y4xt67xoflqbqy2muliparw2uktevletuv7gl4qakjpafgcl7jk2s2er3q", | ||||
|       "PeerId": "12D3KooWG5q6pWJVdPBhDBv9AjWVbUh4xxTAZ7xvgZSjczWuD2Z9", | ||||
|       "MarketBalance": "0", | ||||
|       "PowerBalance": "0", | ||||
|       "SectorSize": 2048, | ||||
|       "Sectors": [ | ||||
|         { | ||||
|           "CommR": { | ||||
|             "/": "bagboea4b5abcboxypcewlkmrat2myu4vthk3ii2pcomak7nhqmdbb6sxlolp2wdf" | ||||
|           }, | ||||
|           "CommD": { | ||||
|             "/": "baga6ea4seaqn3jfixthmdgksv4vhfeuyvr6upw6tvaqbmzmsyxnzosm4pwgnmlq" | ||||
|           }, | ||||
|           "SectorID": 0, | ||||
|           "Deal": { | ||||
|             "PieceCID": { | ||||
|               "/": "baga6ea4seaqn3jfixthmdgksv4vhfeuyvr6upw6tvaqbmzmsyxnzosm4pwgnmlq" | ||||
|             }, | ||||
|             "PieceSize": 2048, | ||||
|             "VerifiedDeal": false, | ||||
|             "Client": "t3spusn5ia57qezc3fwpe3n2lhb4y4xt67xoflqbqy2muliparw2uktevletuv7gl4qakjpafgcl7jk2s2er3q", | ||||
|             "Provider": "t01000", | ||||
|             "Label": "0", | ||||
|             "StartEpoch": 0, | ||||
|             "EndEpoch": 9001, | ||||
|             "StoragePricePerEpoch": "0", | ||||
|             "ProviderCollateral": "0", | ||||
|             "ClientCollateral": "0" | ||||
|           }, | ||||
|           "DealClientKey": { | ||||
|             "Type": "bls", | ||||
|             "PrivateKey": "tFvSRiSg2G3Ssgg0PSYy23XyjaIMXpsmdyG2B7UFLT4=" | ||||
|           }, | ||||
|           "ProofType": 5 | ||||
|         }, | ||||
|         { | ||||
|           "CommR": { | ||||
|             "/": "bagboea4b5abcb6krzypqcczhcnbeyjcqkeo6omfergm336o3kitugh3jgjog2yqq" | ||||
|           }, | ||||
|           "CommD": { | ||||
|             "/": "baga6ea4seaqhondpb2373hjasjplxvbjzi5n5mm4fbbhjxp5ptnbq4cibapkeii" | ||||
|           }, | ||||
|           "SectorID": 1, | ||||
|           "Deal": { | ||||
|             "PieceCID": { | ||||
|               "/": "baga6ea4seaqhondpb2373hjasjplxvbjzi5n5mm4fbbhjxp5ptnbq4cibapkeii" | ||||
|             }, | ||||
|             "PieceSize": 2048, | ||||
|             "VerifiedDeal": false, | ||||
|             "Client": "t3spusn5ia57qezc3fwpe3n2lhb4y4xt67xoflqbqy2muliparw2uktevletuv7gl4qakjpafgcl7jk2s2er3q", | ||||
|             "Provider": "t01000", | ||||
|             "Label": "1", | ||||
|             "StartEpoch": 0, | ||||
|             "EndEpoch": 9001, | ||||
|             "StoragePricePerEpoch": "0", | ||||
|             "ProviderCollateral": "0", | ||||
|             "ClientCollateral": "0" | ||||
|           }, | ||||
|           "DealClientKey": { | ||||
|             "Type": "bls", | ||||
|             "PrivateKey": "tFvSRiSg2G3Ssgg0PSYy23XyjaIMXpsmdyG2B7UFLT4=" | ||||
|           }, | ||||
|           "ProofType": 5 | ||||
|         } | ||||
|       ] | ||||
|     } | ||||
|   ], | ||||
|   "NetworkName": "localnet-6d52dae5-ff29-4bac-a45d-f84e6c07564c", | ||||
|   "VerifregRootKey": { | ||||
|     "Type": "multisig", | ||||
|     "Balance": "0", | ||||
|     "Meta": { | ||||
|       "Signers": [ | ||||
|         "t1ceb34gnsc6qk5dt6n7xg6ycwzasjhbxm3iylkiy" | ||||
|       ], | ||||
|       "Threshold": 1, | ||||
|       "VestingDuration": 0, | ||||
|       "VestingStart": 0 | ||||
|     } | ||||
|   }, | ||||
|   "RemainderAccount": { | ||||
|     "Type": "multisig", | ||||
|     "Balance": "0", | ||||
|     "Meta": { | ||||
|       "Signers": [ | ||||
|         "t1ceb34gnsc6qk5dt6n7xg6ycwzasjhbxm3iylkiy" | ||||
|       ], | ||||
|       "Threshold": 1, | ||||
|       "VestingDuration": 0, | ||||
|       "VestingStart": 0 | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -1,5 +1,6 @@ | ||||
| LOTUS_PATH=~/.lotus-local-net | ||||
| LOTUS_MINER_PATH=~/.lotus-miner-local-net | ||||
| LOTUS_PATH=/root/.lotus-local-net | ||||
| LOTUS_MINER_PATH=/root/.lotus-miner-local-net | ||||
| LOTUS_SKIP_GENESIS_CHECK=_yes_ | ||||
| LOTUS_FEVM_ENABLEETHRPC=true | ||||
| CGO_CFLAGS_ALLOW="-D__BLST_PORTABLE__" | ||||
| CGO_CFLAGS="-D__BLST_PORTABLE__" | ||||
|  | ||||
| @ -2,34 +2,47 @@ | ||||
| 
 | ||||
| lotus --version | ||||
| 
 | ||||
| # # remove old bootnode peer info if present | ||||
| # [ -f /root/.lotus-shared/miner.addr ] && rm /root/.lotus-shared/miner.addr | ||||
| # remove old bootnode peer info if present | ||||
| if [ -f /root/.lotus-shared/miner.addr ]; then | ||||
|   rm /root/.lotus-shared/miner.addr | ||||
| fi | ||||
| 
 | ||||
| ##TODO: generate genesis files inside container instead of bundling in config dir | ||||
| ##something like commands below should work, other scripts/compose will have to be updated to corresponding directories | ||||
| # lotus fetch-params 2048 | ||||
| # lotus-seed pre-seal --sector-size 2KiB --num-sectors 2 | ||||
| # lotus-seed genesis new localnet.json | ||||
| # lotus-seed genesis add-miner localnet.json ~/.genesis-sectors/pre-seal-t01000.json | ||||
| # Check if filecoin-proof-parameters exist; avoid fetching if they do | ||||
| if [ -z "$(find "/var/tmp/filecoin-proof-parameters" -maxdepth 1 -type f)" ]; then | ||||
|   echo "Proof params not found, fetching..." | ||||
|   lotus fetch-params 2048 | ||||
| else | ||||
|   echo "Existing proof params found" | ||||
| fi | ||||
| 
 | ||||
| lotus-seed pre-seal --sector-size 2KiB --num-sectors 2 | ||||
| lotus-seed genesis new localnet.json | ||||
| lotus-seed genesis add-miner localnet.json ~/.genesis-sectors/pre-seal-t01000.json | ||||
| 
 | ||||
| # start daemon | ||||
| nohup lotus daemon  --genesis=/devgen.car --profile=bootstrapper --bootstrap=false > /var/log/lotus.log 2>&1 & | ||||
| nohup lotus daemon --lotus-make-genesis=devgen.car --profile=bootstrapper --genesis-template=localnet.json --bootstrap=false > /var/log/lotus.log 2>&1 & | ||||
| 
 | ||||
| # Loop until the daemon is started | ||||
| echo "Waiting for daemon to start..." | ||||
| while ! grep -q "started ChainNotify channel" /var/log/lotus.log ; do | ||||
|     sleep 5 | ||||
|   sleep 5 | ||||
| done | ||||
| echo "Daemon started." | ||||
| 
 | ||||
| # copy genesis file to shared volume | ||||
| cp /devgen.car /root/.lotus-shared | ||||
| 
 | ||||
| # publish bootnode peer info to shared volume | ||||
| lotus net listen | awk 'NR==1{print}' > /root/.lotus-shared/miner.addr | ||||
| lotus net listen | awk 'NR==2{print}' > /root/.lotus-shared/miner.addr | ||||
| 
 | ||||
| # if miner not already initialized | ||||
| if [ ! -d /root/.lotus-miner-local-net ]; then | ||||
| if [ ! -d $LOTUS_MINER_PATH ]; then | ||||
|   # initialize miner | ||||
|   lotus wallet import --as-default ~/.genesis-sectors/pre-seal-t01000.key | ||||
| 
 | ||||
|   # fund a known account for usage | ||||
|   /fund-account.sh | ||||
| 
 | ||||
|   lotus-miner init --genesis-miner --actor=t01000 --sector-size=2KiB --pre-sealed-sectors=~/.genesis-sectors --pre-sealed-metadata=~/.genesis-sectors/pre-seal-t01000.json --nosync | ||||
| fi | ||||
| 
 | ||||
|  | ||||
| @ -2,23 +2,28 @@ | ||||
| 
 | ||||
| lotus --version | ||||
| 
 | ||||
| ##TODO: paths can use values from lotus-env.env file | ||||
| # Loop until the daemon is started | ||||
| echo "Waiting for miner to share peering info..." | ||||
| while [ ! -f /root/.lotus-shared/miner.addr ]; do | ||||
|   sleep 5 | ||||
| done | ||||
| echo "Resuming..." | ||||
| 
 | ||||
| # if not already initialized | ||||
| if [ ! -f /root/.lotus-local-net/config.toml ]; then | ||||
| if [ ! -f $LOTUS_PATH/config.toml ]; then | ||||
|   # init node config | ||||
|   mkdir $HOME/.lotus-local-net | ||||
|   lotus config default > $HOME/.lotus-local-net/config.toml | ||||
|   mkdir $LOTUS_PATH | ||||
|   lotus config default > $LOTUS_PATH/config.toml | ||||
| 
 | ||||
|   # add bootstrap peer info if available | ||||
|   if [ -f /root/.lotus-shared/miner.addr ]; then | ||||
|     MINER_ADDR=\"$(cat /root/.lotus-shared/miner.addr)\" | ||||
|     # add bootstrap peer id to config file | ||||
|     sed -i "/^\[Libp2p\]/a \ \ BootstrapPeers = [$MINER_ADDR]" $HOME/.lotus-local-net/config.toml | ||||
|     sed -i "/^\[Libp2p\]/a \ \ BootstrapPeers = [$MINER_ADDR]" $LOTUS_PATH/config.toml | ||||
|   else | ||||
|     echo "Bootstrap peer info not found, unable to configure. Manual peering will be required." | ||||
|   fi | ||||
| fi | ||||
| 
 | ||||
| # start node | ||||
| lotus daemon --genesis=/devgen.car | ||||
| lotus daemon --genesis=/root/.lotus-shared/devgen.car | ||||
|  | ||||
| @ -12,7 +12,7 @@ $ laconic-so --stack fixturenet-lotus build-containers | ||||
| ``` | ||||
| ## 3. Deploy the stack | ||||
| ``` | ||||
| $ laconic-so --stack fixturenet-lotus deploy up | ||||
| $ laconic-so --stack fixturenet-lotus deploy --cluster lotus up | ||||
| ``` | ||||
| Correct operation should be verified by checking the container logs with: | ||||
| ``` | ||||
| @ -25,4 +25,4 @@ or by checking the chain status on each node: | ||||
| $ laconic-so --stack fixturenet-lotus deploy exec lotus-miner "lotus status" | ||||
| $ laconic-so --stack fixturenet-lotus deploy exec lotus-node-1 "lotus status" | ||||
| $ laconic-so --stack fixturenet-lotus deploy exec lotus-node-2 "lotus status" | ||||
| ``` | ||||
| ``` | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user