watchtower/blob/justice_kit: add BlobType to JusticeKit struct
This is preparation for later commits where the values returned by member methods will need to be conditioned on the blob type used during decryption.
This commit is contained in:
parent
b82695dbcc
commit
ffe15e2820
@ -100,6 +100,15 @@ type PubKey [33]byte
|
||||
// and for a watchtower to later decrypt if action must be taken. The encoding
|
||||
// format is versioned to allow future extensions.
|
||||
type JusticeKit struct {
|
||||
// BlobType encodes a bitfield that inform the tower of various features
|
||||
// requested by the client when resolving a breach. Examples include
|
||||
// whether the justice transaction contains a reward for the tower, or
|
||||
// whether the channel is a legacy or anchor channel.
|
||||
//
|
||||
// NOTE: This value is not serialized in the encrypted payload. It is
|
||||
// stored separately and added to the JusticeKit after decryption.
|
||||
BlobType Type
|
||||
|
||||
// SweepAddress is the witness program of the output where the client's
|
||||
// fund will be deposited. This value is included in the blobs, as
|
||||
// opposed to the session info, such that the sweep addresses can't be
|
||||
@ -187,17 +196,33 @@ func (b *JusticeKit) HasCommitToRemoteOutput() bool {
|
||||
}
|
||||
|
||||
// CommitToRemoteWitnessScript returns the witness script for the commitment
|
||||
// to-remote p2wkh output, which is the pubkey itself.
|
||||
// to-remote output given the blob type. The script returned will either be for
|
||||
// a p2wpkh to-remote output or an p2wsh anchor to-remote output which includes
|
||||
// a CSV delay.
|
||||
func (b *JusticeKit) CommitToRemoteWitnessScript() ([]byte, error) {
|
||||
if !btcec.IsCompressedPubKey(b.CommitToRemotePubKey[:]) {
|
||||
return nil, ErrNoCommitToRemoteOutput
|
||||
}
|
||||
|
||||
// If this is a blob for an anchor channel, we'll return the p2wsh
|
||||
// output containing a CSV delay of 1.
|
||||
if b.BlobType.IsAnchorChannel() {
|
||||
pk, err := btcec.ParsePubKey(
|
||||
b.CommitToRemotePubKey[:], btcec.S256(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return input.CommitScriptToRemoteConfirmed(pk)
|
||||
}
|
||||
|
||||
return b.CommitToRemotePubKey[:], nil
|
||||
}
|
||||
|
||||
// CommitToRemoteWitnessStack returns a witness stack spending the commitment
|
||||
// to-remote output, which is a regular p2wkh.
|
||||
// to-remote output, which consists of a single signature satisfying either the
|
||||
// legacy or anchor witness scripts.
|
||||
// <to-remote-sig>
|
||||
func (b *JusticeKit) CommitToRemoteWitnessStack() ([][]byte, error) {
|
||||
toRemoteSig, err := b.CommitToRemoteSig.ToSignature()
|
||||
@ -218,11 +243,11 @@ func (b *JusticeKit) CommitToRemoteWitnessStack() ([][]byte, error) {
|
||||
//
|
||||
// NOTE: It is the caller's responsibility to ensure that this method is only
|
||||
// called once for a given (nonce, key) pair.
|
||||
func (b *JusticeKit) Encrypt(key BreachKey, blobType Type) ([]byte, error) {
|
||||
func (b *JusticeKit) Encrypt(key BreachKey) ([]byte, error) {
|
||||
// Encode the plaintext using the provided version, to obtain the
|
||||
// plaintext bytes.
|
||||
var ptxtBuf bytes.Buffer
|
||||
err := b.encode(&ptxtBuf, blobType)
|
||||
err := b.encode(&ptxtBuf, b.BlobType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -236,7 +261,7 @@ func (b *JusticeKit) Encrypt(key BreachKey, blobType Type) ([]byte, error) {
|
||||
// Allocate the ciphertext, which will contain the nonce, encrypted
|
||||
// plaintext and MAC.
|
||||
plaintext := ptxtBuf.Bytes()
|
||||
ciphertext := make([]byte, Size(blobType))
|
||||
ciphertext := make([]byte, Size(b.BlobType))
|
||||
|
||||
// Generate a random 24-byte nonce in the ciphertext's prefix.
|
||||
nonce := ciphertext[:NonceSize]
|
||||
@ -284,7 +309,9 @@ func Decrypt(key BreachKey, ciphertext []byte,
|
||||
|
||||
// If decryption succeeded, we will then decode the plaintext bytes
|
||||
// using the specified blob version.
|
||||
boj := &JusticeKit{}
|
||||
boj := &JusticeKit{
|
||||
BlobType: blobType,
|
||||
}
|
||||
err = boj.decode(bytes.NewReader(plaintext), blobType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -150,6 +150,7 @@ func TestBlobJusticeKitEncryptDecrypt(t *testing.T) {
|
||||
|
||||
func testBlobJusticeKitEncryptDecrypt(t *testing.T, test descriptorTest) {
|
||||
boj := &blob.JusticeKit{
|
||||
BlobType: test.encVersion,
|
||||
SweepAddress: test.sweepAddr,
|
||||
RevocationPubKey: test.revPubKey,
|
||||
LocalDelayPubKey: test.delayPubKey,
|
||||
@ -170,7 +171,7 @@ func testBlobJusticeKitEncryptDecrypt(t *testing.T, test descriptorTest) {
|
||||
|
||||
// Encrypt the blob plaintext using the generated key and
|
||||
// target version for this test.
|
||||
ctxt, err := boj.Encrypt(key, test.encVersion)
|
||||
ctxt, err := boj.Encrypt(key)
|
||||
if err != test.encErr {
|
||||
t.Fatalf("unable to encrypt blob: %v", err)
|
||||
} else if test.encErr != nil {
|
||||
|
@ -137,7 +137,9 @@ func TestLookoutBreachMatching(t *testing.T) {
|
||||
}
|
||||
|
||||
// Construct a justice kit for each possible breach transaction.
|
||||
blobType := blob.FlagCommitOutputs.Type()
|
||||
blob1 := &blob.JusticeKit{
|
||||
BlobType: blobType,
|
||||
SweepAddress: makeAddrSlice(22),
|
||||
RevocationPubKey: makePubKey(1),
|
||||
LocalDelayPubKey: makePubKey(1),
|
||||
@ -145,6 +147,7 @@ func TestLookoutBreachMatching(t *testing.T) {
|
||||
CommitToLocalSig: makeArray64(1),
|
||||
}
|
||||
blob2 := &blob.JusticeKit{
|
||||
BlobType: blobType,
|
||||
SweepAddress: makeAddrSlice(22),
|
||||
RevocationPubKey: makePubKey(2),
|
||||
LocalDelayPubKey: makePubKey(2),
|
||||
@ -156,13 +159,13 @@ func TestLookoutBreachMatching(t *testing.T) {
|
||||
key2 := blob.NewBreachKeyFromHash(&hash2)
|
||||
|
||||
// Encrypt the first justice kit under breach key one.
|
||||
encBlob1, err := blob1.Encrypt(key1, blob.FlagCommitOutputs.Type())
|
||||
encBlob1, err := blob1.Encrypt(key1)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to encrypt sweep detail 1: %v", err)
|
||||
}
|
||||
|
||||
// Encrypt the second justice kit under breach key two.
|
||||
encBlob2, err := blob2.Encrypt(key2, blob.FlagCommitOutputs.Type())
|
||||
encBlob2, err := blob2.Encrypt(key2)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to encrypt sweep detail 2: %v", err)
|
||||
}
|
||||
|
@ -194,6 +194,7 @@ func (t *backupTask) craftSessionPayload(
|
||||
// to-local script, and the remote CSV delay.
|
||||
keyRing := t.breachInfo.KeyRing
|
||||
justiceKit := &blob.JusticeKit{
|
||||
BlobType: t.blobType,
|
||||
SweepAddress: t.sweepPkScript,
|
||||
RevocationPubKey: toBlobPubKey(keyRing.RevocationKey),
|
||||
LocalDelayPubKey: toBlobPubKey(keyRing.ToLocalKey),
|
||||
@ -299,7 +300,7 @@ func (t *backupTask) craftSessionPayload(
|
||||
// Then, we'll encrypt the computed justice kit using the full breach
|
||||
// transaction id, which will allow the tower to recover the contents
|
||||
// after the transaction is seen in the chain or mempool.
|
||||
encBlob, err := justiceKit.Encrypt(key, t.blobType)
|
||||
encBlob, err := justiceKit.Encrypt(key)
|
||||
if err != nil {
|
||||
return hint, nil, err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user