-
Notifications
You must be signed in to change notification settings - Fork 17
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
feat: hardware wallet transactions #98
Conversation
src/RFC-0205_LedgerTransactions.md
Outdated
### Receiving one-sided-stealth | ||
`TODO` | ||
|
||
### Output recovery |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps worth noting that this process only works for interactive outputs.
For legacy one-sided outputs, the helper can watch for A
in scripts (as you note elsewhere), but since it can't complete the DHKE required to decrypt the commitment opening, it can't assert the output is valid and must send it to the signer to be checked.
For stealth one-sided outputs, the helper can't do anything except send such outputs to the signer to be checked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not ideal, but it's not terrible if the helper can at least make a note of all the places `` is found and then batch requests to signer when it's available. The UX would be "42 transactions received. Synch with your device to update the balance".
The synching would be pretty quick then.
That said, I think we'll hone in on a solution where we needn't go down this road.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, for legacy one-sided it's mostly a UX issue, and somewhat a "wait for the signer" issue. For stealth one-sided it's an entirely different problem that does not scale.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it. Some discussion points and clarifying questions.
src/RFC-0205_LedgerTransactions.md
Outdated
\end{aligned} | ||
$$ | ||
|
||
The blinding factor (\\( k_i \\) ) is used as a random nonce when creating the script key. This means the helper can create the public key without the signer present, and the signer can then at a later stage create the private key from the nonce. The key pair (\\( a, A \\) ) is the master key pair from the signer. The private key (\\( a \\) ) is kept secret by the signer at all times. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When you say "master key pair", does this mean that the same a
is used for every transaction?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it would be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, it needs to be for the helper to calculate the Public receive address.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any benefit in doing addition instead of DH?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's faster, and there's no need to do ECDH for this use case.
src/RFC-0205_LedgerTransactions.md
Outdated
### Receiving one-sided-stealth | ||
`TODO` | ||
|
||
### Output recovery |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not ideal, but it's not terrible if the helper can at least make a note of all the places `` is found and then batch requests to signer when it's available. The UX would be "42 transactions received. Synch with your device to update the balance".
The synching would be pretty quick then.
That said, I think we'll hone in on a solution where we needn't go down this road.
src/RFC-0205_LedgerTransactions.md
Outdated
### Process Overview | ||
By splitting the ownership of the [UTXO]'s secret by assigning knowledge of only the script key (\\( k_s \\) ) to the signer, we can lift much of the heavy cryptography like bulletproof creation to the helper device by exposing (\\( k_i \\) ) to it. By looking at how [one-sided-stealth] transactions are created, we can construct the script key in such a way that the helper can calculate the public script key, but cannot calculate the private script key. | ||
|
||
All [UTXO]s created will be created with a script `PushPubkey(K_S)`. The key (\\( k_s \\) ) is created as follows: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I gather, from the discussion below, that you mean to say that we must update the protocol to deprecate the current NOP
default script so that there's always a script key present?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, only change the default behaviour in the default implementation.
The No-Op
script is still useful to have.
Currently, we use No-Op
in all default interactive transactions. that's all I propose we change
src/RFC-0205_LedgerTransactions.md
Outdated
|
||
### Output recovery | ||
When creating outputs the wallet encrypts the blinding factor (\\k_i \\) and value \\( v \\) with (\\( k_H \\) ). | ||
Because the key (\\( k_H \\) ) is calculated from the seed phrase of the signer, this will be the same each time. The helper can try to decrypt each scanned output, when it is successful it knows it has found its own output. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are a
and k_H
the same thing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, k_H
is a fixed helper key derived from a
that's used for encrypting commitment openings. The signer provides it once to the helper, who can then use it for AEAD operations.
src/RFC-0205_LedgerTransactions.md
Outdated
|
||
### Output recovery | ||
When creating outputs the wallet encrypts the blinding factor (\\k_i \\) and value \\( v \\) with (\\( k_H \\) ). | ||
Because the key (\\( k_H \\) ) is calculated from the seed phrase of the signer, this will be the same each time. The helper can try to decrypt each scanned output, when it is successful it knows it has found its own output. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it's a bit worrying to use the same key every time from a security perspective.
Could we perhaps use a strategy similar to the one in BIP-32 for deriving an infinite number of A'
from a single parent private key (signer) or the parent public key (helper)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no security problem here. Encrypted openings use an extended nonce whose entire purpose is to allow for safe key reuse with random nonce sampling. And this key reuse allows for super-fast interactive output scanning during recovery.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, the wallet public key A
doesn't play any role in AEAD decryption during recovery. It only comes into play when testing for offset script public keys, and in that case, there's already a hash-based offset applied that masks the fixed A
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it. Some discussion points and clarifying questions.
Co-authored-by: Cayle Sharrock <CjS77@users.noreply.github.com>
Co-authored-by: Cayle Sharrock <CjS77@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's worth adding a section on generic TariScripts that are not one-sided, e.g. HTLC
src/RFC-0205_LedgerTransactions.md
Outdated
|
||
## Background | ||
|
||
Vanilla [Mimblewimble] only has a single secret per [UTXO], the blinding factor (\\( k_i \\) ), the Tari protocol extends the [Mimblewimble] protocol to include scripting in the form of [TariScript]. This adds a second secret per [UTXO] called the script_key (\\( k_s \\) ). In practical terms this means that while vanilla [Mimblewimble] only requires that a wallet wishing to spend an [UTXO], prove knowledge of (\\( k_i \\) ) by producing the kernel signature, this is not sufficient for Tari. A Tari wallet must also prove knowledge of the script key (\\( k_s \\) ), by producing the script signature. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this true even for Nop scripts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Practically No, Technically yes.
A No-Op
script that just contains the No-Op
operation accepts any input.
So from the wallet submitting the tx, it can submit any Public key as input, and it's still valid. But it still needs to prove it knows the secret key of that public key.
But from the prover side, aka base_node, it just runs, the script and verifies the signature, thus proving knowledge of the script key k_S. How the key was calculated from the script the Base_node does not care.
src/RFC-0205_LedgerTransactions.md
Outdated
|
||
To properly implement hardware wallets we need the following requirements to be met: | ||
* No UTXO can be spent without a user physically approving the transaction on the hardware wallet. | ||
* Users need to verify transaction properties when signing for transactions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you referring to the display of the transaction on the HW wallet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
src/RFC-0205_LedgerTransactions.md
Outdated
\end{aligned} | ||
$$ | ||
|
||
The blinding factor (\\( k_i \\) ) is used as a random nonce when creating the script key. This means the helper can create the public key without the signer present, and the signer can then at a later stage create the private key from the nonce. The key pair (\\( a, A \\) ) is the master key pair from the signer. The private key (\\( a \\) ) is kept secret by the signer at all times. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any benefit in doing addition instead of DH?
src/RFC-0205_LedgerTransactions.md
Outdated
|
||
### Receiving normal one-sided transaction | ||
This can be done by the helper asking the signer for a public key. And advertising this public key as the destination public key for a 1-sided transaction. | ||
The helper can scan the blockchain for this public key. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens to the wallet's Tari Address? Is this not related?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, the wallet calculates the Public script key for the script from the wallet's Tari Address. The only reason that is used is that it's an easily known key that the wallet has the secret key to. So we use that key in place of the TariAddress
src/RFC-0205_LedgerTransactions.md
Outdated
The helper can scan the blockchain for this public key. | ||
|
||
### Receiving one-sided-stealth | ||
`TODO` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just adding a marker here. DNM until resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I see it, this is no different from normal (public) one-sided transactions
Co-authored-by: stringhandler <stringhandler@gmail.com>
Co-authored-by: stringhandler <stringhandler@gmail.com>
Co-authored-by: stringhandler <stringhandler@gmail.com>
Co-authored-by: stringhandler <stringhandler@gmail.com>
src/RFC-0205_HardwareTransactions.md
Outdated
* Helper: This entity is the program that helps the signer construct the transaction, send it over the network and scan the network, aka wallet. | ||
|
||
### Process Overview | ||
By splitting the ownership of the [UTXO]'s secret by assigning knowledge of only the script key (\\( k_s \\) ) to the signer, we can lift much of the heavy cryptography like bulletproof creation to the helper device by exposing (\\( k_i \\) ) to it. By looking at how [one-sided-stealth] transactions are created, we can construct the script key in such a way that the helper can calculate the public script key, but cannot calculate the private script key. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some context on what a UTXO's "secret" is could be helpful here. Really it's two secret values: the commitment mask and the script private key. (The value is private too, but can be easily brute forced and therefore not as relevant.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is discussed two paragraphs up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a few spots where the math-mode separators are written incorrectly, meaning not all math renders properly.
Co-authored-by: Brian Pearce <brianp@users.noreply.github.com>
add extra requirement
add mention of provider requirements
Description
Intial draft for hardware wallet transactions.
Motivation and Context
How Has This Been Tested?