parent
42e47749c0
commit
0882821c4c
|
@ -77,6 +77,10 @@ vdf_bench
|
||||||
# Offer Files
|
# Offer Files
|
||||||
*.offer
|
*.offer
|
||||||
|
|
||||||
|
# Compiled CLVM
|
||||||
|
*.hex
|
||||||
|
main.sym
|
||||||
|
|
||||||
# Dev config react
|
# Dev config react
|
||||||
electron-react/src/dev_config.js
|
electron-react/src/dev_config.js
|
||||||
# React built app
|
# React built app
|
||||||
|
|
|
@ -4,19 +4,11 @@ from typing import List, Optional, Tuple
|
||||||
from src.types.program import Program
|
from src.types.program import Program
|
||||||
from src.types.sized_bytes import bytes32
|
from src.types.sized_bytes import bytes32
|
||||||
from src.util.streamable import streamable, Streamable
|
from src.util.streamable import streamable, Streamable
|
||||||
from src.wallet.cc_wallet import cc_wallet_puzzles
|
from src.types.program import Program
|
||||||
from src.wallet.cc_wallet.ccparent import CCParent
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
@streamable
|
@streamable
|
||||||
class CCInfo(Streamable):
|
class CCInfo(Streamable):
|
||||||
parent_info: List[Tuple[bytes32, Optional[CCParent]]] # {coin.name(): CCParent}
|
my_genesis_checker: Optional[Program] # this is the program
|
||||||
my_colour_name: str
|
lineage_proofs: List[Tuple[bytes32, Optional[Program]]] # {coin.name(): lineage_proof}
|
||||||
|
|
||||||
def puzzle_for_inner_puzzle(self, inner_puzzle: Program) -> Program:
|
|
||||||
genesis_id = bytes.fromhex(self.my_colour_name) if self.my_colour_name else 0
|
|
||||||
return cc_wallet_puzzles.puzzle_for_inner_puzzle(inner_puzzle, genesis_id)
|
|
||||||
|
|
||||||
def genesis_id(self):
|
|
||||||
return self.my_colour_name
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import dataclasses
|
||||||
|
|
||||||
from typing import Any, List, Optional, Tuple
|
from typing import Any, List, Optional, Tuple
|
||||||
|
|
||||||
from blspy import G2Element
|
from blspy import G2Element, AugSchemeMPL
|
||||||
|
|
||||||
from clvm_tools.curry import curry as ct_curry, uncurry
|
from clvm_tools.curry import curry as ct_curry, uncurry
|
||||||
|
|
||||||
|
@ -24,6 +24,9 @@ CC_MOD = load_clvm("cc.clvm", package_or_requirement=__name__)
|
||||||
|
|
||||||
ZERO_GENESIS_MOD = load_clvm("zero-genesis.clvm", package_or_requirement=__name__)
|
ZERO_GENESIS_MOD = load_clvm("zero-genesis.clvm", package_or_requirement=__name__)
|
||||||
|
|
||||||
|
NULL_SIGNATURE = G2Element.generator() * 0
|
||||||
|
|
||||||
|
ANYONE_CAN_SPEND_PUZZLE = Program.to(1) # simply return the conditions
|
||||||
|
|
||||||
# information needed to spend a cc
|
# information needed to spend a cc
|
||||||
# if we ever support more genesis conditions, like a re-issuable coin,
|
# if we ever support more genesis conditions, like a re-issuable coin,
|
||||||
|
@ -164,6 +167,7 @@ def spend_bundle_for_spendable_ccs(
|
||||||
genesis_coin_checker: Program,
|
genesis_coin_checker: Program,
|
||||||
spendable_cc_list: List[SpendableCC],
|
spendable_cc_list: List[SpendableCC],
|
||||||
inner_solutions: List[Program],
|
inner_solutions: List[Program],
|
||||||
|
sigs: Optional[List[G2Element]] = []
|
||||||
) -> SpendBundle:
|
) -> SpendBundle:
|
||||||
"""
|
"""
|
||||||
Given a list of `SpendableCC` objects and inner solutions for those objects, create a `SpendBundle`
|
Given a list of `SpendableCC` objects and inner solutions for those objects, create a `SpendBundle`
|
||||||
|
@ -239,8 +243,10 @@ def spend_bundle_for_spendable_ccs(
|
||||||
parent_coin, next_coin, output_amount, subtotal
|
parent_coin, next_coin, output_amount, subtotal
|
||||||
)
|
)
|
||||||
coin_solutions.append(coin_solution)
|
coin_solutions.append(coin_solution)
|
||||||
|
if sigs is None or sigs == []:
|
||||||
return SpendBundle(coin_solutions, NULL_SIGNATURE)
|
return SpendBundle(coin_solutions, NULL_SIGNATURE)
|
||||||
|
else:
|
||||||
|
return SpendBundle(coin_solutions, AugSchemeMPL.aggregate(sigs))
|
||||||
|
|
||||||
|
|
||||||
def is_cc_mod(inner_f: Program):
|
def is_cc_mod(inner_f: Program):
|
||||||
|
@ -266,6 +272,19 @@ def uncurry_cc(puzzle: Program) -> Optional[Tuple[Program, Program, Program]]:
|
||||||
return mod_hash, genesis_coin_checker, inner_puzzle
|
return mod_hash, genesis_coin_checker, inner_puzzle
|
||||||
|
|
||||||
|
|
||||||
|
def get_lineage_proof_from_coin_and_puz(parent_coin, parent_puzzle):
|
||||||
|
r = uncurry_cc(parent_puzzle)
|
||||||
|
if r:
|
||||||
|
mod_hash, genesis_checker, inner_puzzle = r
|
||||||
|
lineage_proof = lineage_proof_for_cc_parent(parent_coin, inner_puzzle.get_tree_hash())
|
||||||
|
else:
|
||||||
|
if parent_coin.amount == 0:
|
||||||
|
lineage_proof = lineage_proof_for_zero(parent_coin)
|
||||||
|
else:
|
||||||
|
lineage_proof = lineage_proof_for_genesis(parent_coin)
|
||||||
|
return lineage_proof
|
||||||
|
|
||||||
|
|
||||||
def spendable_cc_list_from_coin_solution(
|
def spendable_cc_list_from_coin_solution(
|
||||||
coin_solution: CoinSolution, hash_to_puzzle_f
|
coin_solution: CoinSolution, hash_to_puzzle_f
|
||||||
) -> List[SpendableCC]:
|
) -> List[SpendableCC]:
|
||||||
|
|
|
@ -19,13 +19,6 @@ from src.util.json_util import dict_to_json_str
|
||||||
from src.util.ints import uint64, uint32
|
from src.util.ints import uint64, uint32
|
||||||
from src.wallet.block_record import BlockRecord
|
from src.wallet.block_record import BlockRecord
|
||||||
from src.wallet.cc_wallet.cc_info import CCInfo
|
from src.wallet.cc_wallet.cc_info import CCInfo
|
||||||
from src.wallet.cc_wallet.cc_wallet_puzzles import (
|
|
||||||
get_inner_puzzle_hash_from_puzzle,
|
|
||||||
cc_generate_eve_spend,
|
|
||||||
create_spend_for_auditor,
|
|
||||||
create_spend_for_ephemeral,
|
|
||||||
)
|
|
||||||
from src.wallet.cc_wallet.ccparent import CCParent
|
|
||||||
from src.wallet.transaction_record import TransactionRecord
|
from src.wallet.transaction_record import TransactionRecord
|
||||||
from src.wallet.util.wallet_types import WalletType
|
from src.wallet.util.wallet_types import WalletType
|
||||||
from src.wallet.wallet import Wallet
|
from src.wallet.wallet import Wallet
|
||||||
|
@ -33,13 +26,24 @@ from src.wallet.wallet_coin_record import WalletCoinRecord
|
||||||
from src.wallet.wallet_info import WalletInfo
|
from src.wallet.wallet_info import WalletInfo
|
||||||
from src.wallet.derivation_record import DerivationRecord
|
from src.wallet.derivation_record import DerivationRecord
|
||||||
from src.wallet.cc_wallet import cc_wallet_puzzles
|
from src.wallet.cc_wallet import cc_wallet_puzzles
|
||||||
|
from src.wallet.cc_wallet.cc_utils import (
|
||||||
|
SpendableCC,
|
||||||
|
cc_puzzle_for_inner_puzzle,
|
||||||
|
create_genesis_or_zero_coin_checker,
|
||||||
|
cc_puzzle_hash_for_inner_puzzle_hash,
|
||||||
|
cc_puzzle_for_inner_puzzle,
|
||||||
|
spend_bundle_for_spendable_ccs,
|
||||||
|
genesis_coin_id_for_genesis_coin_checker,
|
||||||
|
coin_as_list,
|
||||||
|
lineage_proof_for_genesis,
|
||||||
|
get_lineage_proof_from_coin_and_puz,
|
||||||
|
uncurry_cc,
|
||||||
|
CC_MOD,
|
||||||
|
ZERO_GENESIS_MOD,
|
||||||
|
ANYONE_CAN_SPEND_PUZZLE
|
||||||
|
)
|
||||||
from dataclasses import replace
|
from dataclasses import replace
|
||||||
|
|
||||||
# TODO: write tests based on wallet tests
|
|
||||||
# TODO: {Matt} compatibility based on deriving innerpuzzle from derivation record
|
|
||||||
# TODO: {Matt} convert this into wallet_state_manager.puzzle_store
|
|
||||||
# TODO: {Matt} add hooks in WebSocketServer for all UI functions
|
|
||||||
|
|
||||||
|
|
||||||
class CCWallet:
|
class CCWallet:
|
||||||
wallet_state_manager: Any
|
wallet_state_manager: Any
|
||||||
|
@ -69,7 +73,7 @@ class CCWallet:
|
||||||
|
|
||||||
self.wallet_state_manager = wallet_state_manager
|
self.wallet_state_manager = wallet_state_manager
|
||||||
|
|
||||||
self.cc_info = CCInfo([], "")
|
self.cc_info = CCInfo(None, [])
|
||||||
info_as_string = bytes(self.cc_info).hex()
|
info_as_string = bytes(self.cc_info).hex()
|
||||||
self.wallet_info = await wallet_state_manager.user_store.create_wallet(
|
self.wallet_info = await wallet_state_manager.user_store.create_wallet(
|
||||||
"CC Wallet", WalletType.COLOURED_COIN.value, info_as_string
|
"CC Wallet", WalletType.COLOURED_COIN.value, info_as_string
|
||||||
|
@ -138,7 +142,7 @@ class CCWallet:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def create_wallet_for_cc(
|
async def create_wallet_for_cc(
|
||||||
wallet_state_manager: Any, wallet: Wallet, colour: str, name: str = None
|
wallet_state_manager: Any, wallet: Wallet, genesis_checker_hex: str, name: str = None
|
||||||
):
|
):
|
||||||
|
|
||||||
self = CCWallet()
|
self = CCWallet()
|
||||||
|
@ -152,7 +156,7 @@ class CCWallet:
|
||||||
|
|
||||||
self.wallet_state_manager = wallet_state_manager
|
self.wallet_state_manager = wallet_state_manager
|
||||||
|
|
||||||
self.cc_info = CCInfo([], colour)
|
self.cc_info = CCInfo(Program.from_bytes(bytes.fromhex(genesis_checker_hex)), [])
|
||||||
info_as_string = bytes(self.cc_info).hex()
|
info_as_string = bytes(self.cc_info).hex()
|
||||||
self.wallet_info = await wallet_state_manager.user_store.create_wallet(
|
self.wallet_info = await wallet_state_manager.user_store.create_wallet(
|
||||||
"CC Wallet", WalletType.COLOURED_COIN.value, info_as_string
|
"CC Wallet", WalletType.COLOURED_COIN.value, info_as_string
|
||||||
|
@ -194,8 +198,8 @@ class CCWallet:
|
||||||
|
|
||||||
amount: uint64 = uint64(0)
|
amount: uint64 = uint64(0)
|
||||||
for record in record_list:
|
for record in record_list:
|
||||||
parent = await self.get_parent_for_coin(record.coin)
|
lineage = await self.get_lineage_proof_for_coin(record.coin)
|
||||||
if parent is not None:
|
if lineage is not None:
|
||||||
amount = uint64(amount + record.coin.amount)
|
amount = uint64(amount + record.coin.amount)
|
||||||
|
|
||||||
self.log.info(
|
self.log.info(
|
||||||
|
@ -235,7 +239,7 @@ class CCWallet:
|
||||||
await self.wallet_state_manager.user_store.update_wallet(self.wallet_info)
|
await self.wallet_state_manager.user_store.update_wallet(self.wallet_info)
|
||||||
|
|
||||||
def get_colour(self):
|
def get_colour(self):
|
||||||
return self.cc_info.my_colour_name
|
return bytes(self.cc_info.my_genesis_checker).hex()
|
||||||
|
|
||||||
async def coin_added(
|
async def coin_added(
|
||||||
self, coin: Coin, height: int, header_hash: bytes32, removals: List[Coin]
|
self, coin: Coin, height: int, header_hash: bytes32, removals: List[Coin]
|
||||||
|
@ -245,14 +249,20 @@ class CCWallet:
|
||||||
|
|
||||||
search_for_parent: bool = True
|
search_for_parent: bool = True
|
||||||
|
|
||||||
inner_puzzle = await self.inner_puzzle_for_cc_puzzle(coin.puzzle_hash)
|
inner_puzzle = await self.inner_puzzle_for_cc_puzhash(coin.puzzle_hash)
|
||||||
future_parent = CCParent(
|
lineage_proof = Program.to(
|
||||||
coin.parent_coin_info, inner_puzzle.get_tree_hash(), coin.amount
|
(
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
coin.parent_coin_info,
|
||||||
|
inner_puzzle.get_tree_hash(),
|
||||||
|
coin.amount,
|
||||||
|
],
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
await self.add_lineage(coin.name(), lineage_proof)
|
||||||
|
|
||||||
await self.add_parent(coin.name(), future_parent)
|
for name, lineage_proofs in self.cc_info.lineage_proofs:
|
||||||
|
|
||||||
for name, ccparent in self.cc_info.parent_info:
|
|
||||||
if coin.parent_coin_info == name:
|
if coin.parent_coin_info == name:
|
||||||
search_for_parent = False
|
search_for_parent = False
|
||||||
break
|
break
|
||||||
|
@ -339,20 +349,15 @@ class CCWallet:
|
||||||
break
|
break
|
||||||
|
|
||||||
if coin is not None:
|
if coin is not None:
|
||||||
if cc_wallet_puzzles.check_is_cc_puzzle(puzzle_program):
|
mod_hash, genesis_coin_checker, inner_puzzle = uncurry_cc(puzzle_program)
|
||||||
inner_puzzle_hash = get_inner_puzzle_hash_from_puzzle(
|
if inner_puzzle is not None:
|
||||||
puzzle_program
|
|
||||||
)
|
|
||||||
|
|
||||||
self.log.info(
|
self.log.info(
|
||||||
f"parent: {coin_name} inner_puzzle for parent is {inner_puzzle_hash.hex()}"
|
f"parent: {coin_name} inner_puzzle for parent is {inner_puzzle}"
|
||||||
)
|
)
|
||||||
|
lineage_proof = get_lineage_proof_from_coin_and_puz(coin, puzzle_program)
|
||||||
await self.add_parent(
|
await self.add_lineage(
|
||||||
coin_name,
|
coin_name,
|
||||||
CCParent(
|
lineage_proof
|
||||||
coin.parent_coin_info, inner_puzzle_hash, coin.amount
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -382,27 +387,15 @@ class CCWallet:
|
||||||
async def get_new_puzzlehash(self) -> bytes32:
|
async def get_new_puzzlehash(self) -> bytes32:
|
||||||
return await self.standard_wallet.get_new_puzzlehash()
|
return await self.standard_wallet.get_new_puzzlehash()
|
||||||
|
|
||||||
def do_replace(self, sexp, magic, magic_replacement):
|
|
||||||
""" Generic way to replace anything inside a SEXP, not used currentyl """
|
|
||||||
if sexp.listp():
|
|
||||||
return self.do_replace(sexp.first(), magic, magic_replacement).cons(
|
|
||||||
self.do_replace(sexp.rest(), magic, magic_replacement)
|
|
||||||
)
|
|
||||||
if sexp.as_atom() == magic:
|
|
||||||
return sexp.to(magic_replacement)
|
|
||||||
return sexp
|
|
||||||
|
|
||||||
def specific_replace(self, old, magic, magic_replacement):
|
|
||||||
"""binutil.assemble is slow, using this hack to swap inner_puzzle_hash. """
|
|
||||||
new = old.replace(magic, magic_replacement)
|
|
||||||
return new
|
|
||||||
|
|
||||||
def puzzle_for_pk(self, pubkey) -> Program:
|
def puzzle_for_pk(self, pubkey) -> Program:
|
||||||
inner_puzzle = self.standard_wallet.puzzle_for_pk(bytes(pubkey))
|
inner_puzzle = self.standard_wallet.puzzle_for_pk(
|
||||||
inner_puzzle_hash = inner_puzzle.get_tree_hash()
|
bytes(pubkey)
|
||||||
cc_puzzle: Program = self.cc_info.puzzle_for_inner_puzzle(inner_puzzle)
|
)
|
||||||
|
cc_puzzle: Program = cc_puzzle_for_inner_puzzle(
|
||||||
|
CC_MOD, self.cc_info.my_genesis_checker, inner_puzzle
|
||||||
|
)
|
||||||
self.base_puzzle_program = bytes(cc_puzzle)
|
self.base_puzzle_program = bytes(cc_puzzle)
|
||||||
self.base_inner_puzzle_hash = inner_puzzle_hash
|
self.base_inner_puzzle_hash = inner_puzzle.get_tree_hash()
|
||||||
return cc_puzzle
|
return cc_puzzle
|
||||||
|
|
||||||
async def get_new_cc_puzzle_hash(self):
|
async def get_new_cc_puzzle_hash(self):
|
||||||
|
@ -416,6 +409,8 @@ class CCWallet:
|
||||||
async def generate_zero_val_coin(
|
async def generate_zero_val_coin(
|
||||||
self, send=True, exclude: List[Coin] = None
|
self, send=True, exclude: List[Coin] = None
|
||||||
) -> Optional[SpendBundle]:
|
) -> Optional[SpendBundle]:
|
||||||
|
if self.cc_info.my_genesis_checker is None:
|
||||||
|
return None
|
||||||
if exclude is None:
|
if exclude is None:
|
||||||
exclude = []
|
exclude = []
|
||||||
coins = await self.standard_wallet.select_coins(0, exclude)
|
coins = await self.standard_wallet.select_coins(0, exclude)
|
||||||
|
@ -425,33 +420,31 @@ class CCWallet:
|
||||||
origin = coins.copy().pop()
|
origin = coins.copy().pop()
|
||||||
origin_id = origin.name()
|
origin_id = origin.name()
|
||||||
|
|
||||||
cc_inner_puzzle = await self.get_new_inner_puzzle()
|
cc_inner = await self.get_new_inner_hash()
|
||||||
cc_inner_puzzle_hash = cc_inner_puzzle.get_tree_hash()
|
cc_puzzle_hash: Program = cc_puzzle_hash_for_inner_puzzle_hash(
|
||||||
|
CC_MOD, self.cc_info.my_genesis_checker, cc_inner
|
||||||
cc_puzzle = self.cc_info.puzzle_for_inner_puzzle(cc_inner_puzzle)
|
)
|
||||||
cc_puzzle_hash = cc_puzzle.get_tree_hash()
|
|
||||||
|
|
||||||
tx = await self.standard_wallet.generate_signed_transaction(
|
tx = await self.standard_wallet.generate_signed_transaction(
|
||||||
uint64(0), cc_puzzle_hash, uint64(0), origin_id, coins
|
uint64(0), cc_puzzle_hash, uint64(0), origin_id, coins
|
||||||
)
|
)
|
||||||
|
full_spend = tx.spend_bundle
|
||||||
self.log.info(f"Generate zero val coin: cc_puzzle_hash is {cc_puzzle_hash}")
|
self.log.info(f"Generate zero val coin: cc_puzzle_hash is {cc_puzzle_hash}")
|
||||||
|
|
||||||
|
# generate eve coin so we can add future lineage_proofs even if we don't eve spend
|
||||||
eve_coin = Coin(origin_id, cc_puzzle_hash, uint64(0))
|
eve_coin = Coin(origin_id, cc_puzzle_hash, uint64(0))
|
||||||
if tx is None or tx.spend_bundle is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
genesis_id = bytes.fromhex(self.cc_info.my_colour_name)
|
await self.add_lineage(eve_coin.name(), Program.to(
|
||||||
eve_spend = cc_generate_eve_spend(eve_coin, cc_inner_puzzle, genesis_id)
|
(
|
||||||
full_spend = SpendBundle.aggregate([tx.spend_bundle, eve_spend])
|
1,
|
||||||
|
[
|
||||||
future_parent = CCParent(
|
eve_coin.parent_coin_info,
|
||||||
eve_coin.parent_coin_info, cc_inner_puzzle_hash, eve_coin.amount
|
cc_inner,
|
||||||
)
|
eve_coin.amount
|
||||||
eve_parent = CCParent(
|
],
|
||||||
origin.parent_coin_info, origin.puzzle_hash, origin.amount
|
)
|
||||||
)
|
))
|
||||||
|
await self.add_lineage(eve_coin.parent_coin_info, Program.to((0, [coin_as_list(origin), 1])))
|
||||||
await self.add_parent(eve_coin.name(), future_parent)
|
|
||||||
await self.add_parent(eve_coin.parent_coin_info, eve_parent)
|
|
||||||
|
|
||||||
if send:
|
if send:
|
||||||
regular_record = TransactionRecord(
|
regular_record = TransactionRecord(
|
||||||
|
@ -540,8 +533,8 @@ class CCWallet:
|
||||||
)
|
)
|
||||||
|
|
||||||
for record in record_list:
|
for record in record_list:
|
||||||
parent = await self.get_parent_for_coin(record.coin)
|
lineage = await self.get_lineage_proof_for_coin(record.coin)
|
||||||
if parent is not None:
|
if lineage is not None:
|
||||||
result.append(record)
|
result.append(record)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -607,20 +600,18 @@ class CCWallet:
|
||||||
sigs.append(signature)
|
sigs.append(signature)
|
||||||
return sigs
|
return sigs
|
||||||
|
|
||||||
async def inner_puzzle_for_cc_puzzle(self, cc_hash: bytes32) -> Program:
|
async def inner_puzzle_for_cc_puzhash(self, cc_hash: bytes32) -> Program:
|
||||||
record: DerivationRecord = await self.wallet_state_manager.puzzle_store.get_derivation_record_for_puzzle_hash(
|
record: DerivationRecord = await self.wallet_state_manager.puzzle_store.get_derivation_record_for_puzzle_hash(
|
||||||
cc_hash.hex()
|
cc_hash.hex()
|
||||||
)
|
)
|
||||||
inner_puzzle: Program = self.standard_wallet.puzzle_for_pk(bytes(record.pubkey))
|
inner_puzzle: Program = self.standard_wallet.puzzle_for_pk(bytes(record.pubkey))
|
||||||
return inner_puzzle
|
return inner_puzzle
|
||||||
|
|
||||||
async def get_parent_for_coin(self, coin) -> Optional[CCParent]:
|
async def get_lineage_proof_for_coin(self, coin) -> Optional[Program]:
|
||||||
parent_info = None
|
for name, proof in self.cc_info.lineage_proofs:
|
||||||
for name, ccparent in self.cc_info.parent_info:
|
|
||||||
if name == coin.parent_coin_info:
|
if name == coin.parent_coin_info:
|
||||||
parent_info = ccparent
|
return proof
|
||||||
|
return None
|
||||||
return parent_info
|
|
||||||
|
|
||||||
async def generate_signed_transaction(
|
async def generate_signed_transaction(
|
||||||
self,
|
self,
|
||||||
|
@ -643,122 +634,31 @@ class CCWallet:
|
||||||
total_amount = sum([x.amount for x in selected_coins])
|
total_amount = sum([x.amount for x in selected_coins])
|
||||||
change = total_amount - amount
|
change = total_amount - amount
|
||||||
|
|
||||||
# first coin becomes the auditor special case
|
|
||||||
auditor = selected_coins.pop()
|
|
||||||
puzzle_hash = auditor.puzzle_hash
|
|
||||||
inner_puzzle: Program = await self.inner_puzzle_for_cc_puzzle(puzzle_hash)
|
|
||||||
|
|
||||||
auditor_info = (
|
|
||||||
auditor.parent_coin_info,
|
|
||||||
inner_puzzle.get_tree_hash(),
|
|
||||||
auditor.amount,
|
|
||||||
)
|
|
||||||
list_of_solutions = []
|
|
||||||
|
|
||||||
# auditees should be (primary_input, innerpuzhash, coin_amount, output_amount)
|
|
||||||
auditees = [
|
|
||||||
(
|
|
||||||
auditor.parent_coin_info,
|
|
||||||
inner_puzzle.get_tree_hash(),
|
|
||||||
auditor.amount,
|
|
||||||
total_amount,
|
|
||||||
)
|
|
||||||
]
|
|
||||||
for coin in selected_coins:
|
|
||||||
coin_inner_puzzle: Program = await self.inner_puzzle_for_cc_puzzle(
|
|
||||||
coin.puzzle_hash
|
|
||||||
)
|
|
||||||
auditees.append(
|
|
||||||
(
|
|
||||||
coin.parent_coin_info,
|
|
||||||
coin_inner_puzzle[coin],
|
|
||||||
coin.amount,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
primaries = [{"puzzlehash": to_address, "amount": amount}]
|
primaries = [{"puzzlehash": to_address, "amount": amount}]
|
||||||
if change > 0:
|
if change > 0:
|
||||||
changepuzzlehash = await self.get_new_inner_hash()
|
changepuzzlehash = await self.get_new_inner_hash()
|
||||||
primaries.append({"puzzlehash": changepuzzlehash, "amount": change})
|
primaries.append({"puzzlehash": changepuzzlehash, "amount": change})
|
||||||
|
|
||||||
innersol = self.standard_wallet.make_solution(primaries=primaries)
|
innersol = self.standard_wallet.make_solution(primaries=primaries)
|
||||||
|
coin = selected_coins.pop()
|
||||||
|
inner_puzzle = await self.inner_puzzle_for_cc_puzhash(coin.puzzle_hash)
|
||||||
|
genesis_id = genesis_coin_id_for_genesis_coin_checker(self.cc_info.my_genesis_checker)
|
||||||
|
innersol_list = [innersol]
|
||||||
|
|
||||||
sigs = sigs + await self.get_sigs(inner_puzzle, innersol)
|
sigs = sigs + await self.get_sigs(inner_puzzle, innersol)
|
||||||
parent_info = await self.get_parent_for_coin(auditor)
|
lineage_proof = await self.get_lineage_proof_for_coin(coin)
|
||||||
assert parent_info is not None
|
assert lineage_proof is not None
|
||||||
|
spendable_cc_list = [SpendableCC(coin, genesis_id, inner_puzzle, lineage_proof)]
|
||||||
|
assert self.cc_info.my_genesis_checker is not None
|
||||||
|
|
||||||
solution = cc_wallet_puzzles.cc_make_solution(
|
|
||||||
self.cc_info.my_colour_name,
|
|
||||||
(
|
|
||||||
parent_info.parent_name,
|
|
||||||
parent_info.inner_puzzle_hash,
|
|
||||||
parent_info.amount,
|
|
||||||
),
|
|
||||||
auditor.amount,
|
|
||||||
inner_puzzle,
|
|
||||||
innersol,
|
|
||||||
auditor_info,
|
|
||||||
auditees,
|
|
||||||
False,
|
|
||||||
)
|
|
||||||
|
|
||||||
puzzle = self.cc_info.puzzle_for_inner_puzzle(inner_puzzle)
|
|
||||||
|
|
||||||
main_coin_solution = CoinSolution(
|
|
||||||
auditor,
|
|
||||||
Program.to([puzzle, solution]),
|
|
||||||
)
|
|
||||||
list_of_solutions.append(main_coin_solution)
|
|
||||||
# main = SpendBundle([main_coin_solution], ZERO96)
|
|
||||||
|
|
||||||
ephemeral_coin_solution = create_spend_for_ephemeral(
|
|
||||||
auditor, auditor, total_amount
|
|
||||||
)
|
|
||||||
list_of_solutions.append(ephemeral_coin_solution)
|
|
||||||
# eph = SpendBundle([ephemeral_coin_solution], ZERO96)
|
|
||||||
|
|
||||||
auditor_coin_colution = create_spend_for_auditor(auditor, auditor)
|
|
||||||
list_of_solutions.append(auditor_coin_colution)
|
|
||||||
# aud = SpendBundle([auditor_coin_colution], ZERO96)
|
|
||||||
|
|
||||||
# loop through remaining spends, treating them as aggregatees
|
|
||||||
for coin in selected_coins:
|
for coin in selected_coins:
|
||||||
coin_inner_puzzle = await self.inner_puzzle_for_cc_puzzle(coin.puzzle_hash)
|
coin_inner_puzzle = await self.inner_puzzle_for_cc_puzhash(coin.puzzle_hash)
|
||||||
innersol = self.standard_wallet.make_solution()
|
innersol = self.standard_wallet.make_solution()
|
||||||
|
innersol_list.append(innersol)
|
||||||
parent_info = await self.get_parent_for_coin(coin)
|
parent_info = await self.get_parent_for_coin(coin)
|
||||||
assert parent_info is not None
|
assert parent_info is not None
|
||||||
sigs = sigs + await self.get_sigs(coin_inner_puzzle, innersol)
|
sigs = sigs + await self.get_sigs(coin_inner_puzzle, innersol)
|
||||||
|
spend_bundle = spend_bundle_for_spendable_ccs(CC_MOD, self.cc_info.my_genesis_checker, spendable_cc_list, innersol_list, sigs)
|
||||||
solution = cc_wallet_puzzles.cc_make_solution(
|
|
||||||
self.cc_info.my_colour_name,
|
|
||||||
(
|
|
||||||
parent_info.parent_name,
|
|
||||||
parent_info.inner_puzzle_hash,
|
|
||||||
parent_info.amount,
|
|
||||||
),
|
|
||||||
coin.amount,
|
|
||||||
coin_inner_puzzle,
|
|
||||||
innersol,
|
|
||||||
auditor_info,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
list_of_solutions.append(
|
|
||||||
CoinSolution(
|
|
||||||
coin,
|
|
||||||
Program.to(
|
|
||||||
[
|
|
||||||
self.cc_info.puzzle_for_inner_puzzle(coin_inner_puzzle),
|
|
||||||
solution,
|
|
||||||
]
|
|
||||||
),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
list_of_solutions.append(create_spend_for_ephemeral(coin, auditor, 0))
|
|
||||||
list_of_solutions.append(create_spend_for_auditor(auditor, coin))
|
|
||||||
|
|
||||||
aggsig = AugSchemeMPL.aggregate(sigs)
|
|
||||||
spend_bundle = SpendBundle(list_of_solutions, aggsig)
|
|
||||||
|
|
||||||
tx_record = TransactionRecord(
|
tx_record = TransactionRecord(
|
||||||
confirmed_at_index=uint32(0),
|
confirmed_at_index=uint32(0),
|
||||||
created_at_time=uint64(int(time.time())),
|
created_at_time=uint64(int(time.time())),
|
||||||
|
@ -778,11 +678,13 @@ class CCWallet:
|
||||||
|
|
||||||
return tx_record
|
return tx_record
|
||||||
|
|
||||||
async def add_parent(self, name: bytes32, parent: Optional[CCParent]):
|
async def add_lineage(self, name: bytes32, lineage: Optional[Program]):
|
||||||
self.log.info(f"Adding parent {name}: {parent}")
|
self.log.info(f"Adding parent {name}: {lineage}")
|
||||||
current_list = self.cc_info.parent_info.copy()
|
current_list = self.cc_info.lineage_proofs.copy()
|
||||||
current_list.append((name, parent))
|
current_list.append((name, lineage))
|
||||||
cc_info: CCInfo = CCInfo(current_list, self.cc_info.my_colour_name)
|
cc_info: CCInfo = CCInfo(
|
||||||
|
self.cc_info.my_genesis_checker, current_list
|
||||||
|
)
|
||||||
await self.save_info(cc_info)
|
await self.save_info(cc_info)
|
||||||
|
|
||||||
async def save_info(self, cc_info: CCInfo):
|
async def save_info(self, cc_info: CCInfo):
|
||||||
|
@ -803,32 +705,27 @@ class CCWallet:
|
||||||
|
|
||||||
origin = coins.copy().pop()
|
origin = coins.copy().pop()
|
||||||
origin_id = origin.name()
|
origin_id = origin.name()
|
||||||
# self.add_parent(origin_id, origin_id)
|
|
||||||
|
|
||||||
cc_info: CCInfo = CCInfo([], origin_id.hex())
|
cc_inner_hash = await self.get_new_inner_hash()
|
||||||
await self.save_info(cc_info)
|
await self.add_lineage(origin_id, Program.to((0, [coin_as_list(origin), 0])))
|
||||||
|
genesis_coin_checker = create_genesis_or_zero_coin_checker(origin_id)
|
||||||
|
|
||||||
cc_inner_puzzle = await self.get_new_inner_puzzle()
|
minted_cc_puzzle_hash = cc_puzzle_hash_for_inner_puzzle_hash(
|
||||||
cc_puzzle = cc_wallet_puzzles.puzzle_for_inner_puzzle(
|
CC_MOD, genesis_coin_checker, cc_inner_hash
|
||||||
cc_inner_puzzle, origin_id
|
|
||||||
)
|
)
|
||||||
cc_puzzle_hash = cc_puzzle.get_tree_hash()
|
|
||||||
|
|
||||||
tx_record: Optional[
|
tx_record: Optional[
|
||||||
TransactionRecord
|
TransactionRecord
|
||||||
] = await self.standard_wallet.generate_signed_transaction(
|
] = await self.standard_wallet.generate_signed_transaction(
|
||||||
amount, cc_puzzle_hash, uint64(0), origin_id, coins
|
amount, minted_cc_puzzle_hash, uint64(0), origin_id, coins
|
||||||
)
|
)
|
||||||
self.log.info(f"cc_puzzle_hash is {cc_puzzle_hash}")
|
|
||||||
eve_coin = Coin(origin_id, cc_puzzle_hash, amount)
|
|
||||||
if tx_record is None or tx_record.spend_bundle is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
eve_spend = cc_generate_eve_spend(eve_coin, cc_inner_puzzle, origin_id)
|
lineage_proofs = [(origin_id, lineage_proof_for_genesis(origin))]
|
||||||
|
cc_info: CCInfo = CCInfo(genesis_coin_checker, lineage_proofs)
|
||||||
full_spend = SpendBundle.aggregate([tx_record.spend_bundle, eve_spend])
|
await self.save_info(cc_info)
|
||||||
return full_spend
|
return tx_record.spend_bundle
|
||||||
|
|
||||||
|
"""
|
||||||
async def create_spend_bundle_relative_amount(
|
async def create_spend_bundle_relative_amount(
|
||||||
self, cc_amount, zero_coin: Coin = None
|
self, cc_amount, zero_coin: Coin = None
|
||||||
):
|
):
|
||||||
|
@ -862,7 +759,7 @@ class CCWallet:
|
||||||
output_created = coin
|
output_created = coin
|
||||||
else:
|
else:
|
||||||
innersol = self.standard_wallet.make_solution()
|
innersol = self.standard_wallet.make_solution()
|
||||||
innerpuz: Program = await self.inner_puzzle_for_cc_puzzle(coin.puzzle_hash)
|
innerpuz: Program = await self.inner_puzzle_for_cc_puzhash(coin.puzzle_hash)
|
||||||
|
|
||||||
parent_info = await self.get_parent_for_coin(coin)
|
parent_info = await self.get_parent_for_coin(coin)
|
||||||
assert parent_info is not None
|
assert parent_info is not None
|
||||||
|
@ -894,8 +791,4 @@ class CCWallet:
|
||||||
spend_bundle = SpendBundle(list_of_solutions, aggsig)
|
spend_bundle = SpendBundle(list_of_solutions, aggsig)
|
||||||
return spend_bundle
|
return spend_bundle
|
||||||
|
|
||||||
# Create an offer spend bundle for chia given an amount of relative change (i.e -400 or 1000)
|
"""
|
||||||
# This is to be aggregated together with a coloured coin offer to ensure that the trade happens
|
|
||||||
async def create_spend_bundle_relative_chia(self, chia_amount: uint64):
|
|
||||||
self.log.error("Not implemented")
|
|
||||||
# TODO MATT: Implement
|
|
||||||
|
|
|
@ -1450,7 +1450,7 @@ class WalletStateManager:
|
||||||
for wallet_id in self.wallets:
|
for wallet_id in self.wallets:
|
||||||
wallet = self.wallets[wallet_id]
|
wallet = self.wallets[wallet_id]
|
||||||
if wallet.wallet_info.type == WalletType.COLOURED_COIN.value:
|
if wallet.wallet_info.type == WalletType.COLOURED_COIN.value:
|
||||||
if wallet.cc_info.genesis_id() == colour:
|
if bytes(wallet.cc_info.my_genesis_checker).hex() == colour:
|
||||||
return wallet
|
return wallet
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
|
@ -103,13 +103,14 @@ class TestCCWallet:
|
||||||
await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
|
await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
|
||||||
await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
|
await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
|
||||||
|
|
||||||
colour = cc_wallet.cc_info.genesis_id()
|
assert cc_wallet.cc_info.my_genesis_checker is not None
|
||||||
|
colour = cc_wallet.get_colour()
|
||||||
|
|
||||||
cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
|
cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
|
||||||
wallet_node_2.wallet_state_manager, wallet2, colour
|
wallet_node_2.wallet_state_manager, wallet2, colour
|
||||||
)
|
)
|
||||||
|
|
||||||
assert cc_wallet.cc_info.genesis_id() == cc_wallet_2.cc_info.genesis_id()
|
assert cc_wallet.cc_info.my_genesis_checker == cc_wallet_2.cc_info.my_genesis_checker
|
||||||
|
|
||||||
cc_2_hash = await cc_wallet_2.get_new_inner_hash()
|
cc_2_hash = await cc_wallet_2.get_new_inner_hash()
|
||||||
tx_record = await cc_wallet.generate_signed_transaction(uint64(60), cc_2_hash)
|
tx_record = await cc_wallet.generate_signed_transaction(uint64(60), cc_2_hash)
|
||||||
|
@ -206,13 +207,14 @@ class TestCCWallet:
|
||||||
await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
|
await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
|
||||||
await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
|
await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
|
||||||
|
|
||||||
colour = cc_wallet.cc_info.genesis_id()
|
assert cc_wallet.cc_info.my_genesis_checker is not None
|
||||||
|
colour = cc_wallet.get_colour()
|
||||||
|
|
||||||
cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
|
cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
|
||||||
wallet_node_2.wallet_state_manager, wallet2, colour
|
wallet_node_2.wallet_state_manager, wallet2, colour
|
||||||
)
|
)
|
||||||
|
|
||||||
assert cc_wallet.cc_info.genesis_id() == cc_wallet_2.cc_info.genesis_id()
|
assert cc_wallet.cc_info.my_genesis_checker == cc_wallet_2.cc_info.my_genesis_checker
|
||||||
|
|
||||||
await cc_wallet_2.generate_zero_val_coin()
|
await cc_wallet_2.generate_zero_val_coin()
|
||||||
|
|
||||||
|
@ -264,14 +266,14 @@ class TestCCWallet:
|
||||||
await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
|
await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
|
||||||
await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
|
await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
|
||||||
|
|
||||||
assert cc_wallet.cc_info.genesis_id() is not None
|
assert cc_wallet.cc_info.my_genesis_checker is not None
|
||||||
colour = cc_wallet.cc_info.genesis_id()
|
colour = cc_wallet.get_colour()
|
||||||
|
|
||||||
cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
|
cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(
|
||||||
wallet_node_2.wallet_state_manager, wallet2, colour
|
wallet_node_2.wallet_state_manager, wallet2, colour
|
||||||
)
|
)
|
||||||
|
|
||||||
assert cc_wallet.cc_info.genesis_id() == cc_wallet_2.cc_info.genesis_id()
|
assert cc_wallet.cc_info.my_genesis_checker == cc_wallet_2.cc_info.my_genesis_checker
|
||||||
|
|
||||||
cc_2_hash = await cc_wallet_2.get_new_inner_hash()
|
cc_2_hash = await cc_wallet_2.get_new_inner_hash()
|
||||||
tx_record = await cc_wallet.generate_signed_transaction(uint64(60), cc_2_hash)
|
tx_record = await cc_wallet.generate_signed_transaction(uint64(60), cc_2_hash)
|
||||||
|
|
Loading…
Reference in New Issue