Skip to content
This repository has been archived by the owner on Mar 28, 2023. It is now read-only.

Utility belt #113

Draft
wants to merge 53 commits into
base: main
Choose a base branch
from
Draft

Utility belt #113

wants to merge 53 commits into from

Conversation

Shadowfiend
Copy link
Contributor

WIP

This will be used in certain utilities, but is only included as a dev
dependency.
This script helps look up and output liquidation information starting at
a certain date as a CSV.
This looks up the true owners for one or more operator address
delegations, indirecting through grants if needed.
This utility will allow straightforward ingesting of a CSV that lists
keeps that may need recovery, key shares, and operator BTC receive
addresses or funder refund addresses, and coordinate BTC transaction
construction for BTC held in keeps that have provided their key shares.
This is useful for the refunds script, which needs to look up owners for
certain processes.
The script now pulls keeps and checks for their operators' associated
key shares, the keeps' associated status on-chain, the BTC still held in
the keep, and looks up their BTC beneficiary address information on disk
for liquidations.

Still missing:

 - Constructing the split transaction for liquidation refunds.
 - All misfund handling.
@pdyraga
Copy link
Member

pdyraga commented Dec 7, 2020

💪

bitcoin.js now separates most of the hard work into exported functions
that can be used elsewhere---for example, in the refund script...
These are reported as errors in the resulting CSV, and can be handled
later/separately without blocking other transactions from being
processed.
This is more closely aligned with how we're tracking requests.
It used to depend on the key shares directory, but some callers will
only have the keep address and needn't know about how to construct
directory paths.
A few things were wrong:

- The expected JSON object keys were incorrect.
- The matchAll call and its results were overly complex.
Allow specifying a fixed BTC fee as a -f parameter, and handle misfunds
end-to-end including reading and verifying the refund address, resolving
the funding input, and building, signing, and broadcasting the refund
transaction.

The final CSV output for these transactions includes the transaction id
and the signed transaction data for debugging or broadcasting elsewhere
if needed.
This allows constructing a raw transaction with one input and multiple
outputs.
The error is caught higher up and can allow for bubbling e.g. the error
messages from keep-ecdsa.
Before, error output only was being reported, but this could prevent
seeing certain explanatory outputs that the executable is putting on
stdout.
TokenStaking was being constructed as if it didn't need a set address,
whereas it does.
The address recovered by accounts.recover can be in a different checksum
mode than the one included in the JSON payload.
The inner content of *pubs can match the address regexp, so switch the
check around. Also, *pubs are accepted even if more than one is
detected, provided that all matched *pubs are the same. This can happen
in cases where the message is a JSON payload of a type that can be
outputted by some tools to include more info than just the *pub.
When a beneficiary is read, a fresh address is generated for it by
iterating the *pub's key index until an address is found with no
transactions. Currently only p2pkh addresses are generated.
Hasn't been checked yet as the necessary key material isn't yet
available.
This ensures that when a withElectrumClient call occurs inside an
existing withElectrumClient call, the client and connection are reused
instead of another client being created and another connection being
opened to the server.
Using the new withElectrumClient nested reuse, a single connection can
be used for all refunds handled in the script, instead of many
connections being required throughout.
Without this, the funding info is unavailable and the liquidation split
transaction can't be constructed properly.
Shadowfiend and others added 23 commits December 10, 2020 23:33
All misfunding-related errors said the same thing, which was related to
liquidation. They now correctly reflect the stage of misfund processing
that they are reporting an error on.
Before, it was hardcoded to p2pkh. Now, an xpub yields p2pkh, ypub
yields p2wpkh-p2sh, and zpub yields p2wpkh.
Missing key shares are now called out, and too many key shares gets a
separate error.
Sometimes the `exit` event on the process will fire before the stdout
stream has finished reporting all of its output. In these cases, if the
process completed successfully, the output needs to be allowed to finish
before the public key and signature can be extracted.

The code now waits for the `close` event on the stdout stream, and
throws in cases where the final output cannot be split into public key
and signature correctly.
This makes it easier, when analyzing the CSV output, to see cases where
multiple deposits are being refunded to one BTC address, or one deposit
has multiple slots to one BTC address. Both are potential signs that
there was an issue with beneficiary handling.
The original approach was straight up broken, and didn't invoke
resolveGrantee correctly to boot. Previously, the grant lookup would
always resolve to the 0 grant.
The script probably needs to be renamed...
By default, all console.log output goes to the debug output. By default,
debug output is suppressed. --debug enables debug output.

Also, fix moment handling of the passed date; it was always being parsed
as an integer, which meant the start date was always effectively "since
the system was turned on".
When keep-ecdsa was invoked and exited, sometimes the exit would happen
before the process would finish notifying the JS process of output. The
result would be partial output that could not be parsed correctly. To
fix this, a 'close' event handler was added on the stdout stream when
the process exited. Unfortunately, this broke behavior when stdout had
already been closed, and made the whole process hang.

Whether or not the output has ended is now tracked, and if it has it is
immediately processed on process exit. If not, an event handler is
attached to process the output at that point.
Because refunds were running in parallel, there was no guarantee that
two refunds would use separate generated addresses from a *pub. Refunds
are now processed serially. Beneficiary addresses also track their
lastIndex for *pubs, so that already-checked addresses can be skipped on
subsequent refunds.
This is more reflective of the kind of output being used, and helps in
cases where command-line tools suppress debug output.
This allows for event searches to stop searching past a certain block,
in addition to the existing functionality that allows starting the
search at a certain block.
The regex in question was trying to overgeneralize between standard and
bech32 addresses, and it was truncating some bech32 addresses in the
process.
The old subgraph is no longer generating.
This was already fixed for liquidation recovery, but the fix didn't get
ported over to misfund address handling, so longer-than-36-character
bech32 addresses were getting lopped off.
These were joined by , due to default array serialization, but of course
this wreaked absolute havoc on CSV parsing.
This script is mostly a helper to look at the StakingPortBacker and
check whether the ported stakes still need to be repaid. Notably, it's
really a Keep script, not a tBTC script, but it reuses infrastructure
that tbtc.js has that doesn't exist on the Keep repo yet.
This flag prevents broadcasting of the refund transaction, replacing its
transaction ID in the final CSV with a note indicating that this is a dry run.
By default, bin/owner-lookup.js continues to check the new staking
contract for ownership info. However, if used as a library, it now
allows the return of the grant type (as "no grant", "direct grant", and
"managed grant") and allows the caller to substitute the old staking
contract for the `TokenStaking` key of the passed contracts.

To do this, the process for resolving TokenGrantStakes changes
completely. The old staking contract provides no strategy for looking
up an event for the stake delegation using just the operator address,
meaning the owner is needed in order to properly resolve information
about the grant---but this script uses the grant info to resolve
the owner!

Instead, the new approach directly reads the on-chain storage slots and
heuristically determines if a contract is a TokenGrantStake. If it does,
it assumes the fourth slot represents the grant id, and resolves the
grant id in this way.
The new output includes the grant type (as "no grant"/"direct grant"/
"managed grant"), the owner (even if no stake copying occurred), and
separately reports a boolean indicating if the owner used stake copying
or not.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants