This commit is contained in:
Yostra 2020-01-31 12:03:52 -08:00
parent bb09b90c28
commit cc796768aa
3 changed files with 58 additions and 54 deletions

View File

@ -6,6 +6,10 @@ def make_create_coin_condition(puzzle_hash, amount):
return [ConditionOpcode.CREATE_COIN, puzzle_hash, amount] return [ConditionOpcode.CREATE_COIN, puzzle_hash, amount]
def make_assert_aggsig_condition(pubkey):
return [ConditionOpcode.AGG_SIG, pubkey]
def make_assert_coin_consumed_condition(coin_name): def make_assert_coin_consumed_condition(coin_name):
return [ConditionOpcode.ASSERT_COIN_CONSUMED, coin_name] return [ConditionOpcode.ASSERT_COIN_CONSUMED, coin_name]

View File

@ -32,7 +32,7 @@ class TestMempool:
block = blocks[1] block = blocks[1]
async for _ in full_node_1.block(peer_protocol.Block(block)): async for _ in full_node_1.block(peer_protocol.Block(block)):
spend_bundle = wallet_a.generate_signed_transaction(1000, receiver_puzzlehash, [block.body.coinbase]) spend_bundle = wallet_a.generate_signed_transaction(1000, receiver_puzzlehash, block.body.coinbase)
tx: peer_protocol.Transaction = peer_protocol.Transaction(spend_bundle) tx: peer_protocol.Transaction = peer_protocol.Transaction(spend_bundle)
async for _ in full_node_1.transaction(tx): async for _ in full_node_1.transaction(tx):
outbound: OutboundMessage = _ outbound: OutboundMessage = _
@ -54,7 +54,7 @@ class TestMempool:
async for _ in full_node_1.block(peer_protocol.Block(block)): async for _ in full_node_1.block(peer_protocol.Block(block)):
pass pass
spend_bundle1 = wallet_a.generate_signed_transaction(1000, receiver_puzzlehash, [block.body.coinbase]) spend_bundle1 = wallet_a.generate_signed_transaction(1000, receiver_puzzlehash, block.body.coinbase)
tx1: peer_protocol.Transaction = peer_protocol.Transaction(spend_bundle1) tx1: peer_protocol.Transaction = peer_protocol.Transaction(spend_bundle1)
async for _ in full_node_1.transaction(tx1): async for _ in full_node_1.transaction(tx1):
outbound: OutboundMessage = _ outbound: OutboundMessage = _
@ -62,7 +62,7 @@ class TestMempool:
assert outbound.message.function == "maybe_transaction" assert outbound.message.function == "maybe_transaction"
other_receiver = WalletTool() other_receiver = WalletTool()
spend_bundle2 = wallet_a.generate_signed_transaction(1000, other_receiver.get_new_puzzlehash(), [block.body.coinbase]) spend_bundle2 = wallet_a.generate_signed_transaction(1000, other_receiver.get_new_puzzlehash(), block.body.coinbase)
tx2: peer_protocol.Transaction = peer_protocol.Transaction(spend_bundle2) tx2: peer_protocol.Transaction = peer_protocol.Transaction(spend_bundle2)
async for _ in full_node_1.transaction(tx2): async for _ in full_node_1.transaction(tx2):
pass pass
@ -88,14 +88,14 @@ class TestMempool:
async for _ in full_node_1.block(peer_protocol.Block(block)): async for _ in full_node_1.block(peer_protocol.Block(block)):
pass pass
spend_bundle1 = wallet_a.generate_signed_transaction(1000, receiver_puzzlehash, [block.body.coinbase]) spend_bundle1 = wallet_a.generate_signed_transaction(1000, receiver_puzzlehash, block.body.coinbase)
tx1: peer_protocol.Transaction = peer_protocol.Transaction(spend_bundle1) tx1: peer_protocol.Transaction = peer_protocol.Transaction(spend_bundle1)
async for _ in full_node_1.transaction(tx1): async for _ in full_node_1.transaction(tx1):
outbound: OutboundMessage = _ outbound: OutboundMessage = _
# Maybe transaction means that it's accepted in mempool # Maybe transaction means that it's accepted in mempool
assert outbound.message.function == "maybe_transaction" assert outbound.message.function == "maybe_transaction"
spend_bundle2 = wallet_a.generate_signed_transaction(1000, receiver_puzzlehash, [block.body.coinbase], 1) spend_bundle2 = wallet_a.generate_signed_transaction(1000, receiver_puzzlehash, block.body.coinbase, fee=1)
tx2: peer_protocol.Transaction = peer_protocol.Transaction(spend_bundle2) tx2: peer_protocol.Transaction = peer_protocol.Transaction(spend_bundle2)
async for _ in full_node_1.transaction(tx2): async for _ in full_node_1.transaction(tx2):

View File

@ -1,17 +1,20 @@
from typing import List, Optional from typing import List, Optional, Dict
import clvm import clvm
from os import urandom from os import urandom
from blspy import ExtendedPrivateKey from blspy import ExtendedPrivateKey
from src.types.hashable import ProgramHash, CoinSolution, SpendBundle, Program, BLSSignature, Coin from src.types.hashable import ProgramHash, CoinSolution, SpendBundle, Program, BLSSignature, Coin
from src.util.Conditions import conditions_by_opcode from src.util.Conditions import conditions_by_opcode, ConditionVarPair, ConditionOpcode
from src.util.consensus import hash_key_pairs_for_conditions_dict, conditions_for_solution from src.util.consensus import hash_key_pairs_for_conditions_dict, conditions_for_solution
from src.wallet import keychain
from src.wallet.BLSPrivateKey import BLSPrivateKey from src.wallet.BLSPrivateKey import BLSPrivateKey
from src.wallet.puzzles.p2_conditions import puzzle_for_conditions from src.wallet.puzzles.p2_conditions import puzzle_for_conditions
from src.wallet.puzzles.p2_delegated_conditions import solution_for_conditions
from src.wallet.puzzles.p2_delegated_puzzle import puzzle_for_pk from src.wallet.puzzles.p2_delegated_puzzle import puzzle_for_pk
from src.wallet.puzzles.puzzle_utils import make_assert_coin_consumed_condition, make_assert_min_time_condition, \ from src.wallet.puzzles.puzzle_utils import make_assert_coin_consumed_condition, make_assert_min_time_condition, \
make_assert_my_coin_id_condition, make_create_coin_condition make_assert_my_coin_id_condition, make_create_coin_condition, make_assert_block_index_exceeds_condition, \
make_assert_block_age_exceeds_condition, make_assert_aggsig_condition
class WalletTool: class WalletTool:
@ -68,41 +71,50 @@ class WalletTool:
blskey = BLSPrivateKey(privatekey) blskey = BLSPrivateKey(privatekey)
return blskey.sign(value) return blskey.sign(value)
def make_solution(self, primaries=[], min_time=0, me={}, consumed=[]): def make_solution(self, condition_dic: Dict[ConditionOpcode, List[ConditionVarPair]]):
ret = [] ret = []
for primary in primaries:
ret.append(make_create_coin_condition( for con_list in condition_dic.values():
primary['puzzlehash'], primary['amount'])) for cvp in con_list:
for coin in consumed: if cvp.opcode == ConditionOpcode.CREATE_COIN:
ret.append(make_assert_coin_consumed_condition(coin)) ret.append(make_create_coin_condition(cvp.var1, cvp.var2))
if min_time > 0: if cvp.opcode == ConditionOpcode.AGG_SIG:
ret.append(make_assert_min_time_condition(min_time)) ret.append(make_assert_aggsig_condition(cvp.var1))
if me: if cvp.opcode == ConditionOpcode.ASSERT_COIN_CONSUMED:
ret.append(make_assert_my_coin_id_condition(me['id'])) ret.append(make_assert_coin_consumed_condition(cvp.var1))
if cvp.opcode == ConditionOpcode.ASSERT_MIN_TIME:
ret.append(make_assert_min_time_condition(cvp.var1))
if cvp.opcode == ConditionOpcode.ASSERT_MY_COIN_ID:
ret.append(make_assert_my_coin_id_condition(cvp.var1))
if cvp.opcode == ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS:
ret.append(make_assert_block_index_exceeds_condition(cvp.var1))
if cvp.opcode == ConditionOpcode.ASSERT_BLOCK_AGE_EXCEEDS:
ret.append(make_assert_block_age_exceeds_condition(cvp.var1))
return clvm.to_sexp_f([puzzle_for_conditions(ret), []]) return clvm.to_sexp_f([puzzle_for_conditions(ret), []])
def generate_unsigned_transaction(self, amount, newpuzzlehash, utxos: List[Coin], fee: int = 0): def generate_unsigned_transaction(self, amount, newpuzzlehash, coin: Coin,
condition_dic: Dict[ConditionOpcode, List[ConditionVarPair]]= {}, fee: int = 0):
spends = [] spends = []
output_created = False spend_value = coin.amount
spend_value = sum([coin.amount for coin in utxos])
change = spend_value - amount - fee change = spend_value - amount - fee
for coin in utxos: puzzle_hash = coin.puzzle_hash
puzzle_hash = coin.puzzle_hash pubkey, secretkey = self.get_keys(puzzle_hash)
puzzle = puzzle_for_pk(pubkey.serialize())
if ConditionOpcode.CREATE_COIN not in condition_dic:
condition_dic = {ConditionOpcode.CREATE_COIN: []}
pubkey, secretkey = self.get_keys(puzzle_hash) output = ConditionVarPair(ConditionOpcode.CREATE_COIN, newpuzzlehash, amount)
puzzle = puzzle_for_pk(pubkey.serialize()) condition_dic[output.opcode].append(output)
if output_created is False: if change > 0:
primaries = [{'puzzlehash': newpuzzlehash, 'amount': amount}] changepuzzlehash = self.get_new_puzzlehash()
if change > 0: change_output = ConditionVarPair(ConditionOpcode.CREATE_COIN, changepuzzlehash, change)
changepuzzlehash = self.get_new_puzzlehash() condition_dic[output.opcode].append(change_output)
primaries.append( solution = self.make_solution(condition_dic)
{'puzzlehash': changepuzzlehash, 'amount': change}) else:
# add change coin into temp_utxo set solution = self.make_solution(condition_dic)
solution = self.make_solution(primaries=primaries)
output_created = True spends.append((puzzle, CoinSolution(coin, solution)))
else:
solution = self.make_solution(consumed=[coin.name()])
spends.append((puzzle, CoinSolution(coin, solution)))
return spends return spends
def sign_transaction(self, spends: (Program, [CoinSolution])): def sign_transaction(self, spends: (Program, [CoinSolution])):
@ -124,22 +136,10 @@ class WalletTool:
spend_bundle = SpendBundle(solution_list, aggsig) spend_bundle = SpendBundle(solution_list, aggsig)
return spend_bundle return spend_bundle
def generate_signed_transaction(self, amount, newpuzzlehash, coins: List[Coin], fee: int = 0) -> Optional[SpendBundle]: def generate_signed_transaction(self, amount, newpuzzlehash, coin: Coin,
transaction = self.generate_unsigned_transaction(amount, newpuzzlehash, coins, fee) condition_dic: Dict[ConditionOpcode, List[ConditionVarPair]] = {},
fee: int = 0) -> Optional[SpendBundle]:
transaction = self.generate_unsigned_transaction(amount, newpuzzlehash, coin, condition_dic, fee)
if transaction is None: if transaction is None:
return None return None
return self.sign_transaction(transaction) return self.sign_transaction(transaction)
"""
Copyright 2018 Chia Network Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""