Skip to content

Commit

Permalink
Merge pull request #338 from Chia-Network/ak.update-to-chia-blockchai…
Browse files Browse the repository at this point in the history
…n-2.4.2

CHIA-992: Update pool reference code to be compatible with chia-blockchain 2.4.2
  • Loading branch information
emlowe authored Aug 16, 2024
2 parents 84aa0bf + b24a361 commit 0ee875e
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 55 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ name: black-action
on: [push, pull_request]
jobs:
linter_name:
name: runner / black formatter
name: runner & black formatter
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: rickstaa/action-black@v1
- uses: psf/black@stable
with:
black_args: ". --check"
src: "."
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ farmers, and points should be acknowledged and accumulated points returned in th


### Difficulty adjustment algorithm
This is a simple difficulty adjustment algorithm executed by the pool. The pool can also improve this or change it
This is a simple difficulty adjustment algorithm executed by the pool. The pool can also improve this or change it
however they wish. The farmer can provide their own `suggested_difficulty`, and the pool can decide whether or not
to update that farmer's difficulty. Be careful to only accept the latest authentication_public_key when setting
difficulty or pool payout info. The initial reference client and pool do not use the `suggested_difficulty`.
Expand All @@ -143,7 +143,7 @@ difficulty or pool payout info. The initial reference client and pool do not use
- If < 45 minutes:
- If have < 300 partials at this difficulty, maintain same difficulty
- Else, multiply the difficulty by (24 * 3600 / (time taken for 300 partials))

The 6 hours is used to handle rare cases where a farmer's storage drops dramatically. The 45 minutes is similar, but
for less extreme cases. Finally, the last case of < 45 minutes should properly handle users with increasing space,
or slightly decreasing space. This targets 300 partials per day, but different numbers can be used based on
Expand All @@ -158,8 +158,8 @@ latest seen authentication key for that launcher_id.
### Install and run (Testnet)
To run a pool, you must use this along with the main branch of `chia-blockchain`.

1. Checkout the `main` branch of `chia-blockchain`, and install it. Checkout this repo in another directory next to (not inside) `chia-blockchain`.
If you want to connect to testnet, use `export CHIA_ROOT=~/.chia/testnet9`, or whichever testnet you want to join, and
1. Checkout the `main` branch of `chia-blockchain`, and install it. Checkout this repo in another directory next to (not inside) `chia-blockchain`.
If you want to connect to testnet, use `export CHIA_ROOT=~/.chia/testnet9`, or whichever testnet you want to join, and
run `chia configure -t true`. You can also directly use the `pools.testnet9` branch, although this branch will
be removed in the future (or past).

Expand All @@ -168,14 +168,14 @@ If you want to connect to testnet, use `export CHIA_ROOT=~/.chia/testnet9`, or w
3. Change the `wallet_fingerprint` and `wallet_id` in the `config.yaml` config file, using the information from the first
key you created in step 2. These can be obtained by doing `chia wallet show`.

4. Do `chia keys show` and get the first address for each of the keys created in step 2. Put these into the `config.yaml`
4. Do `chia keys show` and get the first address for each of the keys created in step 2. Put these into the `config.yaml`
config file in `default_target_address` and `pool_fee_address` respectively.
5. Change the `pool_url` in `config.yaml` to point to your external ip or hostname.

5. Change the `pool_url` in `config.yaml` to point to your external ip or hostname.
This must match exactly with what the user enters into their UI or CLI, and must start with https://.
6. Start the node using `chia start farmer`, and log in to a different key (not the two keys created for the pool).
This will be referred to as the farmer's key here. Sync up your wallet on testnet for the farmer key.

6. Start the node using `chia start farmer`, and log in to a different key (not the two keys created for the pool).
This will be referred to as the farmer's key here. Sync up your wallet on testnet for the farmer key.
You can log in to a key by running `chia wallet show` and then choosing each wallet in turn, to make them start syncing.

7. Create a venv (different from chia-blockchain) and start the pool server using the following commands:
Expand All @@ -195,19 +195,19 @@ INFO:root:Obtaining balance: {'confirmed_wallet_balance': 0, 'max_send_amount':
```

8. Create a pool nft (on the farmer key) by doing `chia plotnft create -s pool -u https://127.0.0.1:80`, or whatever host:port you want
to use for your pool. Approve it and wait for transaction confirmation. This url must match *exactly* with what the
to use for your pool. Approve it and wait for transaction confirmation. This url must match *exactly* with what the
pool uses.

9. Do `chia plotnft show` to ensure that your plotnft is created. Now start making some plots for this pool nft.
You can make plots by specifying the -c argument in `chia plots create`. Make sure to *not* use the `-p` argument. The
You can make plots by specifying the -c argument in `chia plots create`. Make sure to *not* use the `-p` argument. The
value you should use for -c is the `P2 singleton address` from `chia plotnft show` output.
You can start with small k25 plots and see if partials are submitted from the farmer to the pool server. The output
will be the following in the pool if everything is working:
```
INFO:root:Returning {'new_difficulty': 1963211364}, time: 0.017535686492919922 singleton: 0x1f8dab79a614a82f9834c8f395f5fe195ae020807169b71a10218b9788a7a573
```

Please send a message to @sorgente711 on keybase if you have questions about the 9 steps explained above. All other questions
should be sent to the #pools channel in keybase.
should be sent to the #pools channel in keybase.



49 changes: 30 additions & 19 deletions pool/pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
from math import floor
from typing import Any, Callable, Dict, List, Optional, Set, Tuple

from blspy import AugSchemeMPL, G1Element
from chia.consensus.block_rewards import calculate_pool_reward
from chia.consensus.constants import ConsensusConstants
from chia.consensus.default_constants import DEFAULT_CONSTANTS
from chia.consensus.pot_iterations import calculate_iterations_quality
from chia.full_node.signage_point import SignagePoint
from chia.pools.pool_puzzles import (
Expand All @@ -29,6 +29,7 @@
PutFarmerRequest,
)
from chia.rpc.full_node_rpc_client import FullNodeRpcClient
from chia.rpc.wallet_request_types import SendTransactionMultiResponse
from chia.rpc.wallet_rpc_client import WalletRpcClient
from chia.types.blockchain_format.coin import Coin
from chia.types.blockchain_format.proof_of_space import verify_and_get_quality_string
Expand All @@ -43,6 +44,8 @@
from chia.util.ints import uint8, uint16, uint32, uint64
from chia.util.lru_cache import LRUCache
from chia.wallet.transaction_record import TransactionRecord
from chia.wallet.util.tx_config import TXConfig
from chia_rs import AugSchemeMPL, G1Element

from .difficulty_adjustment import get_new_difficulty
from .record import FarmerRecord
Expand Down Expand Up @@ -317,9 +320,9 @@ async def collect_pool_rewards_loop(self) -> None:
if singleton_tip is None:
continue

singleton_coin_record: Optional[
CoinRecord
] = await self.node_rpc_client.get_coin_record_by_name(singleton_tip.name())
singleton_coin_record: Optional[CoinRecord] = (
await self.node_rpc_client.get_coin_record_by_name(singleton_tip.name())
)
if singleton_coin_record is None:
continue
if singleton_coin_record.spent:
Expand Down Expand Up @@ -406,9 +409,9 @@ async def create_payment_loop(self) -> None:
async with self.store.lock:
# Get the points of each farmer, as well as payout instructions. Here a chia address is used,
# but other blockchain addresses can also be used.
points_and_ph: List[
Tuple[uint64, bytes]
] = await self.store.get_farmer_points_and_payout_instructions()
points_and_ph: List[Tuple[uint64, bytes]] = (
await self.store.get_farmer_points_and_payout_instructions()
)
total_points = sum([pt for (pt, ph) in points_and_ph])
if total_points > 0:
mojo_per_point = floor(amount_to_distribute / total_points)
Expand Down Expand Up @@ -466,10 +469,18 @@ async def submit_payment_loop(self) -> None:
# blockchain_fee = 0.00001 * (10 ** 12) * len(payment_targets)
blockchain_fee: uint64 = uint64(0)
try:
tx_config = TXConfig(
max_coin_amount=uint64(DEFAULT_CONSTANTS.MAX_COIN_AMOUNT),
min_coin_amount=uint64(0),
excluded_coin_amounts=[uint64(0)],
excluded_coin_ids=[],
reuse_puzhash=False,
)
assert self.wallet_rpc_client
transaction: TransactionRecord = await self.wallet_rpc_client.send_transaction_multi(
self.wallet_id, payment_targets, fee=blockchain_fee
response: SendTransactionMultiResponse = await self.wallet_rpc_client.send_transaction_multi(
self.wallet_id, payment_targets, tx_config, fee=blockchain_fee
)
transaction: TransactionRecord = response.transaction
except ValueError as e:
self.log.error(f"Error making payment: {e}")
await asyncio.sleep(10)
Expand All @@ -484,7 +495,7 @@ async def submit_payment_loop(self) -> None:
or not (peak_height - transaction.confirmed_at_height) > self.confirmation_security_threshold
):
assert self.wallet_rpc_client
transaction = await self.wallet_rpc_client.get_transaction(self.wallet_id, transaction.name)
transaction = await self.wallet_rpc_client.get_transaction(transaction.name)
peak_height = self.blockchain_state["peak"].height
self.log.info(
f"Waiting for transaction to obtain {self.confirmation_security_threshold} confirmations"
Expand Down Expand Up @@ -556,9 +567,9 @@ async def check_and_confirm_partial(self, partial: PostPartialRequest, points_re
self.recent_points_added.put(pos_hash, uint64(1))

# Now we need to check to see that the singleton in the blockchain is still assigned to this pool
singleton_state_tuple: Optional[
Tuple[CoinSpend, PoolState, bool]
] = await self.get_and_validate_singleton_state(partial.payload.launcher_id)
singleton_state_tuple: Optional[Tuple[CoinSpend, PoolState, bool]] = (
await self.get_and_validate_singleton_state(partial.payload.launcher_id)
)

if singleton_state_tuple is None:
self.log.info(f"Invalid singleton {partial.payload.launcher_id}")
Expand Down Expand Up @@ -616,9 +627,9 @@ async def add_farmer(self, request: PostFarmerRequest, metadata: RequestMetadata
f"Farmer with launcher_id {request.payload.launcher_id} already known.",
)

singleton_state_tuple: Optional[
Tuple[CoinSpend, PoolState, bool]
] = await self.get_and_validate_singleton_state(request.payload.launcher_id)
singleton_state_tuple: Optional[Tuple[CoinSpend, PoolState, bool]] = (
await self.get_and_validate_singleton_state(request.payload.launcher_id)
)

if singleton_state_tuple is None:
return error_dict(PoolErrorCode.INVALID_SINGLETON, f"Invalid singleton {request.payload.launcher_id}")
Expand Down Expand Up @@ -694,9 +705,9 @@ async def update_farmer(self, request: PutFarmerRequest, metadata: RequestMetada
if farmer_record is None:
return error_dict(PoolErrorCode.FARMER_NOT_KNOWN, f"Farmer with launcher_id {launcher_id} not known.")

singleton_state_tuple: Optional[
Tuple[CoinSpend, PoolState, bool]
] = await self.get_and_validate_singleton_state(launcher_id)
singleton_state_tuple: Optional[Tuple[CoinSpend, PoolState, bool]] = (
await self.get_and_validate_singleton_state(launcher_id)
)

if singleton_state_tuple is None:
return error_dict(PoolErrorCode.INVALID_SINGLETON, f"Invalid singleton {request.payload.launcher_id}")
Expand Down
6 changes: 3 additions & 3 deletions pool/pool_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
import aiohttp
import yaml
from aiohttp import web
from blspy import AugSchemeMPL, G2Element
from chia.consensus.constants import ConsensusConstants
from chia.consensus.constants import ConsensusConstants, replace_str_to_bytes
from chia.consensus.default_constants import DEFAULT_CONSTANTS
from chia.protocols.pool_protocol import (
POOL_PROTOCOL_VERSION,
Expand All @@ -30,6 +29,7 @@
from chia.util.hash import std_hash
from chia.util.ints import uint8, uint32, uint64
from chia.util.json_util import obj_to_response
from chia_rs import AugSchemeMPL, G2Element

from .pool import Pool
from .record import FarmerRecord
Expand Down Expand Up @@ -291,7 +291,7 @@ async def start_pool_server(pool_store: Optional[AbstractPoolStore] = None):
global runner
config = load_config(DEFAULT_ROOT_PATH, "config.yaml")
overrides = config["network_overrides"]["constants"][config["selected_network"]]
constants: ConsensusConstants = DEFAULT_CONSTANTS.replace_str_to_bytes(**overrides)
constants: ConsensusConstants = replace_str_to_bytes(DEFAULT_CONSTANTS, **overrides)
server = PoolServer(config, constants, pool_store)
await server.start()

Expand Down
2 changes: 1 addition & 1 deletion pool/record.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from dataclasses import dataclass

from blspy import G1Element
from chia.pools.pool_wallet_info import PoolState
from chia.types.blockchain_format.sized_bytes import bytes32
from chia.types.coin_spend import CoinSpend
from chia.util.ints import uint64
from chia.util.streamable import Streamable, streamable
from chia_rs import G1Element


@streamable
Expand Down
23 changes: 15 additions & 8 deletions pool/singleton.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@
from chia.pools.pool_wallet_info import PoolState
from chia.rpc.full_node_rpc_client import FullNodeRpcClient
from chia.rpc.wallet_rpc_client import WalletRpcClient
from chia.types.announcement import Announcement
from chia.types.blockchain_format.coin import Coin
from chia.types.blockchain_format.program import Program
from chia.types.blockchain_format.sized_bytes import bytes32
from chia.types.coin_record import CoinRecord
from chia.types.coin_spend import CoinSpend
from chia.types.spend_bundle import SpendBundle
from chia.util.ints import uint32, uint64
from chia.wallet.conditions import AssertCoinAnnouncement, Condition
from chia.wallet.transaction_record import TransactionRecord
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG

from .record import FarmerRecord

Expand Down Expand Up @@ -173,7 +174,7 @@ async def create_absorb_transaction(
farmer_record.launcher_id
)
assert launcher_coin_record is not None
coin_announcements: List[Announcement] = []
coin_announcements: Tuple[Condition, ...] = tuple()

all_spends: List[CoinSpend] = []
for reward_coin_record in reward_coin_records:
Expand All @@ -192,19 +193,25 @@ async def create_absorb_transaction(
farmer_record.delay_puzzle_hash,
)
if fee_amount > 0:
coin_announcements.append(Announcement(reward_coin_record.coin.name(), b"$"))
coin_announcements = (
*coin_announcements,
AssertCoinAnnouncement(asserted_id=reward_coin_record.coin.name(), asserted_msg=b"$"),
)
last_spend = absorb_spend[0]
all_spends += absorb_spend
# TODO(pool): handle the case where the cost exceeds the size of the block

if len(coin_announcements) > 0:
# address can be anything
assert wallet_rpc_client
signed_transaction: TransactionRecord = await wallet_rpc_client.create_signed_transaction(
additions=[{"amount": uint64(1), "puzzle_hash": fee_target_puzzle_hash}],
fee=uint64(fee_amount * len(coin_announcements)),
coin_announcements=coin_announcements,
)
signed_transaction: TransactionRecord = (
await wallet_rpc_client.create_signed_transactions(
additions=[{"amount": uint64(1), "puzzle_hash": fee_target_puzzle_hash}],
tx_config=DEFAULT_TX_CONFIG,
fee=uint64(fee_amount * len(coin_announcements)),
extra_conditions=(*coin_announcements,),
)
).signed_tx
fee_spend_bundle: Optional[SpendBundle] = signed_transaction.spend_bundle
else:
fee_spend_bundle = None
Expand Down
6 changes: 3 additions & 3 deletions pool/store/mariadb_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@
import aiomysql
import pymysql # type: ignore
import yaml
from blspy import G1Element
from chia.pools.pool_wallet_info import PoolState
from chia.types.blockchain_format.sized_bytes import bytes32
from chia.types.coin_spend import CoinSpend
from chia.util.ints import uint64
from chia_rs import G1Element

from ..record import FarmerRecord
from ..util import RequestMetadata
from .abstract import AbstractPoolStore

pymysql.converters.encoders[uint64] = pymysql.converters.escape_int
pymysql.converters.conversions = pymysql.converters.encoders.copy()
pymysql.converters.conversions.update(pymysql.converters.decoders)
pymysql.converters.conversions = pymysql.converters.encoders.copy() # type:ignore
pymysql.converters.conversions.update(pymysql.converters.decoders) # type:ignore


class MariadbPoolStore(AbstractPoolStore):
Expand Down
2 changes: 1 addition & 1 deletion pool/store/sqlite_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
from typing import Dict, List, Optional, Set, Tuple

import aiosqlite
from blspy import G1Element
from chia.pools.pool_wallet_info import PoolState
from chia.types.blockchain_format.sized_bytes import bytes32
from chia.types.coin_spend import CoinSpend
from chia.util.ints import uint64
from chia_rs import G1Element

from ..record import FarmerRecord
from ..util import RequestMetadata
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ def read(fname):


dependencies = [
"chia-blockchain==2.0.0",
"blspy==2.0.3",
"chia-blockchain==2.4.2",
"chia_rs>=0.5.2",
"setuptools~=56.1.0",
"aiosqlite==0.20.0",
"aiohttp==3.9.5",
Expand Down

0 comments on commit 0ee875e

Please sign in to comment.