Skip to content

Commit

Permalink
Add "merge" command to combine outputs into a reasonable number.
Browse files Browse the repository at this point in the history
  • Loading branch information
maaku committed Apr 14, 2022
1 parent ae5780b commit 829aaf3
Showing 1 changed file with 84 additions and 0 deletions.
84 changes: 84 additions & 0 deletions webcash/walletclient.py
Expand Up @@ -158,16 +158,20 @@ def create_webcash_wallet():
def get_info():
webcash_wallet = load_webcash_wallet()

count = 0
amount = 0
for webcash in webcash_wallet["webcash"]:
webcash = SecretWebcash.deserialize(webcash)
amount += webcash.amount
count += 1

print(f"Total amount stored in this wallet (if secure): e{amount}")

walletdepths = webcash_wallet["walletdepths"]
print(f"walletdepth: {walletdepths}")

print(f"outputs: {count}")

@click.group()
def cli():
pass
Expand Down Expand Up @@ -634,6 +638,86 @@ def pay(amount, memo=""):

save_webcash_wallet(webcash_wallet)

@cli.command("merge")
@click.option("--group", default="20", help="Maximum number of outputs to merge at once")
@click.option("--max", default="50000000", help="Maximum output size")
@click.option("--memo", default="", help="Memo field for the transaction log")
def merge(group, max, memo):
max_inputs = int(group)
max_amount = deserialize_amount(max)
print(f"group: {max_inputs}, max: {max_amount}")
webcash_wallet = load_webcash_wallet()
webcash_to_merge = []
for webcash in webcash_wallet["webcash"]:
webcash = SecretWebcash.deserialize(webcash)
if webcash.amount < max_amount:
webcash_to_merge.append(webcash)
print(f"found {len(webcash_to_merge)} webcash to merge")
while len(webcash_to_merge) > 1:
inputs = []
while 0 < len(webcash_to_merge) and len(inputs) < max_inputs:
inputs.append(webcash_to_merge.pop())

total = sum([wc.amount for wc in inputs])
change = total

outputs = []
while 0 < change:
change_amount = min(change, max_amount)
change_secret = generate_new_secret(webcash_wallet, chain_code="CHANGE")
outputs.append(SecretWebcash(amount=decimal.Decimal(change_amount), secret_value=change_secret))
change -= change_amount

replace_request = {
"webcashes": [str(wc) for wc in inputs],
"new_webcashes": [str(wc) for wc in outputs],
"legalese": webcash_wallet["legalese"],
}
print(f"merging {len(replace_request['webcashes'])} outputs into {len(replace_request['new_webcashes'])}")

# Save the webcash to the wallet in case there is a network error while
# attempting to replace it.
unconfirmed_webcash = replace_request["new_webcashes"]
webcash_wallet["unconfirmed"].extend(unconfirmed_webcash)
save_webcash_wallet(webcash_wallet)

# Send replacement request to the server
response = requests.post("https://webcash.org/api/v1/replace", json=replace_request)
if response.status_code != 200:
raise Exception("Something went wrong on the server: ", response.content)

# remove old webcash
for wc in replace_request["webcashes"]:
webcash_wallet["webcash"].remove(wc)

# add new webcash
webcash_wallet["webcash"].extend(replace_request["new_webcashes"])

# remove unconfirmed webcashes
for wc in unconfirmed_webcash:
webcash_wallet["unconfirmed"].remove(wc)

# store a record of this transaction
webcash_wallet["log"].append({
"type": "merge",
"memo": " ".join(memo),
"amount": 0,
"input_webcashes": replace_request["webcashes"],
"output_webcash": replace_request["new_webcashes"],
"timestamp": str(datetime.datetime.now()),
})

# save the wallet
save_webcash_wallet(webcash_wallet)

# add outputs to our merge list
for wc in outputs:
if wc.amount < max_amount:
webcash_to_merge.append(wc)

print("Done!")


def main():
# Create a new webcash wallet if one does not already exist.
if not os.path.exists(WALLET_NAME):
Expand Down

0 comments on commit 829aaf3

Please sign in to comment.