Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lnrpc: Add destination output information (pkScript, output index, amount and if output belongs to the node) #5476

Merged
merged 6 commits into from
Mar 23, 2022

Conversation

bjarnemagnussen
Copy link
Contributor

Fixes #2835.

This PR adds destination output information to the TransactionDetail structure returned by both RPC GetTransactions and SubscribeTransactions.

The additional fields include the output script (PkScript), amount (Amount), index (OutputIndex) and a bool (IsOurAddress) to denote if the output belongs to the node's internal wallet or not.

Since all of this information is already available when constructing the TransactionDetail, this information can just be added as it can be useful in many applications and depending on the use case may also solve issue #4826.

Note

The output index does not simply correspond to the position in the DestOutput array, as unrecognized outputs are skipped:

for _, txOut := range wireTx.TxOut {
_, outAddresses, _, err := txscript.ExtractPkScriptAddrs(
txOut.PkScript, chainParams,
)
if err != nil {
// Skip any unsupported addresses to prevent
// other transactions from not being returned.
continue
}

@guggero guggero self-requested a review July 6, 2021 15:11
@guggero guggero added rpc Related to the RPC interface wallet The wallet (lnwallet) which LND uses labels Jul 6, 2021
Copy link
Collaborator

@guggero guggero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great PR, thank you! This additional info should be very useful.

I think we should merge the new info with the address internally and deprecate the address field in the RPC. But other than that looks great to me!

lnwallet/interface.go Outdated Show resolved Hide resolved
lnrpc/rpc.proto Outdated Show resolved Hide resolved
@guggero
Copy link
Collaborator

guggero commented Jul 8, 2021

The output index does not simply correspond to the position in the DestOutput array, as unrecognized outputs are skipped:

Perhaps we could even optimize the output here. If we can't parse the address, we set the address to nil (and empty string on the RPC) but still include the other details. That way we could get rid of that continue statement you linked.

@bjarnemagnussen
Copy link
Contributor Author

bjarnemagnussen commented Jul 9, 2021

The output index does not simply correspond to the position in the DestOutput array, as unrecognized outputs are skipped:

Perhaps we could even optimize the output here. If we can't parse the address, we set the address to nil (and empty string on the RPC) but still include the other details. That way we could get rid of that continue statement you linked.

I agree and think this makes a lot of sense. My only reservation is in the way that the address is calculated. As it currently is, the returned address for a single output script is a slice of potential multiple addresses. Normally the slice will just contain a single valid address that corresponds to exactly the output script. However, in the extremely rare case of a MultiSig script NOT encoded via a P2SH, the returned slice of addresses will simply contain a list of P2PKH addresses from the multisig script (since the direct multisig script does not have an address representation).

I have therefore added some logic to make sure in this case we return an empty address.

@bjarnemagnussen
Copy link
Contributor Author

I have squashed the new changes:

  • Remove DestAddresses from the lnwallet.TransactionDetail structure as it is otherwise redundantly available via OutputDetails and just re-populated to the RPC for backwards compatibility.
  • Introduced another field to OutputDetail called OutputType that will be of OutputScriptType to denote the kind of output script. However, I am not sure if alternatively defining it as a string and using the String() method on a ScriptClass is the more pragmatic solution? (See the definition here)

Copy link
Collaborator

@guggero guggero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks for adding the new enum. Just one comment about the enum values and a few nits, other than that I think this is ready.

lnrpc/rpc.proto Outdated Show resolved Hide resolved
lnrpc/rpc_utils.go Outdated Show resolved Hide resolved
@bjarnemagnussen bjarnemagnussen force-pushed the upstream/feat/dest-outputs branch 2 times, most recently from 506cc07 to 73547d9 Compare July 12, 2021 10:57
@guggero guggero requested a review from wpaulino July 12, 2021 11:16
Copy link
Collaborator

@guggero guggero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the super quick updates, LGTM 🎉

@wpaulino wpaulino removed their request for review August 16, 2021 17:24
@Roasbeef Roasbeef added the P3 might get fixed, nice to have label Aug 31, 2021
@Roasbeef Roasbeef added this to the v0.15.0 milestone Nov 23, 2021
@lightninglabs-deploy
Copy link

@ellemouton: review reminder

Copy link
Collaborator

@ellemouton ellemouton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left some comments. Also, needs a rebase :)

lnwallet/btcwallet/btcwallet.go Outdated Show resolved Hide resolved
lnrpc/rpc.proto Outdated
OutputScriptType output_type = 1;

// The address
string address = 2;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the first commit, the OutputDetail struct has an array of addresses instead of just 1. I assumed that is for a multisig script or something? in anycase, if we do a slice there, then this should also be be repeated. otherwise, the struct should be changed to just have 1 addr too.

Copy link
Contributor Author

@bjarnemagnussen bjarnemagnussen Mar 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason to use a slice for it was to deprecate DestAddresses but still expose it on the RPC for backwards compatibility. However, we can also re-introduce the DestAddresses directly to the interface and have the OutputDetail only contain the single destination address if available?


var address string
if len(o.Addresses) == 1 {
address = o.Addresses[0].EncodeAddress()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah so following up on my comment from before, what about the other addresses here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DestAddresses field is a bit weird, because if an output is not re-presentable by an address (e.g. due to NonStandard type or the MultiSigType), then the indices in the DestAddresses do not correspond to the outputs.

The reason that MultiSigType returns a slice of addresses, is because this is the case where the multisig script is directly put inside the scriptPubKey, hence not behind a hash. Therefore it cannot be represented by an address. It is questionable if a slice of addresses for the pubkeys referred to in the multisig script is helpful though. :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok cool, chatted to oli about this and he agrees with you 👍

@bjarnemagnussen
Copy link
Contributor Author

Thanks @ellemouton for your comments! I have rebased this PR. Also I have tried to clarify the weird behaviour of the legacy DestAddresses field in a comment and am open to handle it differently.

Copy link
Collaborator

@ellemouton ellemouton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tACK 🚀

i think it needs another rebase @bjarnemagnussen

A new `DestOutputs` field contains additional information on destinations of a transaction described with the `TransactionDetail` structure.

The additional information inside `DestOuputs` denote the output script and amount, as well as a flag `IsOurAddress` if the address is controlled by the node's wallet.
Adds the output script and amount to the `DestOutput` field of `TransactionDetails`, as well as sets the flag `isOurAddress` if the output is controlled by the node's wallet.
With `OutputDetail` now containing the destination addresses, the `DestAddresses` field can be removed from the `lnwallet.TransactionDetail`. It is already populated when needed for backwards compatibility to `lnrpc.TransactionDetail` via `OutputDetail.Addresses`.
@bjarnemagnussen
Copy link
Contributor Author

Thanks @ellemouton! I have rebased and added release notes!

@guggero guggero merged commit 802544b into lightningnetwork:master Mar 23, 2022
@bjarnemagnussen bjarnemagnussen deleted the upstream/feat/dest-outputs branch March 23, 2022 11:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P3 might get fixed, nice to have rpc Related to the RPC interface wallet The wallet (lnwallet) which LND uses
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature request] Include amounts in subscribeTransactions for each dest address
5 participants