Skip to content

Commit

Permalink
Merge pull request #896 from lightninglabs/poc-refactor
Browse files Browse the repository at this point in the history
Lightning channel proof-of-concept refactor commits
  • Loading branch information
ffranr authored May 13, 2024
2 parents c8978aa + dce8515 commit 91a51d6
Show file tree
Hide file tree
Showing 21 changed files with 237 additions and 50 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ env:
# go needs absolute directories, using the $HOME variable doesn't work here.
GOPATH: /home/runner/work/go

GO_VERSION: '1.21.4'
GO_VERSION: '1.22.3'

jobs:
#######################
Expand All @@ -32,6 +32,9 @@ jobs:
- name: git checkout
uses: actions/checkout@v3

- name: Setup go environment
uses: ./.github/actions/setup-go

- name: docker image cache
uses: jpribyl/[email protected]
continue-on-error: true
Expand All @@ -46,6 +49,9 @@ jobs:
- name: git checkout
uses: actions/checkout@v3

- name: Setup go environment
uses: ./.github/actions/setup-go

- name: Generate RPC stubs and check REST annotations
run: make rpc-check

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ defaults:
shell: bash

env:
GO_VERSION: 1.21.4
GO_VERSION: 1.22.3

jobs:
main:
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.21.4-alpine as builder
FROM golang:1.22.3-alpine as builder

# Force Go to use the cgo based DNS resolver. This is required to ensure DNS
# queries required to connect to linked containers succeed.
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ DOCKER_TOOLS = docker run \
-v $(shell bash -c "go env GOMODCACHE || (mkdir -p /tmp/go-modcache; echo /tmp/go-modcache)"):/tmp/build/.modcache \
-v $$(pwd):/build taproot-assets-tools

GO_VERSION = 1.21.4
GO_VERSION = 1.22.3

GREEN := "\\033[0;32m"
NC := "\\033[0m"
Expand Down
40 changes: 39 additions & 1 deletion asset/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,21 @@ func (i ID) String() string {
return hex.EncodeToString(i[:])
}

// Record returns a TLV record that can be used to encode/decode an ID to/from a
// TLV stream.
//
// NOTE: This is part of the tlv.RecordProducer interface.
func (i *ID) Record() tlv.Record {
const recordSize = sha256.Size

// Note that we set the type here as zero, as when used with a
// tlv.RecordT, the type param will be used as the type.
return tlv.MakeStaticRecord(0, i, recordSize, IDEncoder, IDDecoder)
}

// Ensure ID implements the tlv.RecordProducer interface.
var _ tlv.RecordProducer = (*ID)(nil)

// ID computes an asset's unique identifier from its metadata.
func (g Genesis) ID() ID {
tagHash := g.TagHash()
Expand Down Expand Up @@ -1714,6 +1729,26 @@ func (a *Asset) EncodeRecords() []tlv.Record {
return a.encodeRecords(EncodeNormal)
}

// Record returns a TLV record that can be used to encode/decode an Asset
// to/from a TLV stream.
//
// NOTE: This is part of the tlv.RecordProducer interface.
func (a *Asset) Record() tlv.Record {
sizeFunc := func() uint64 {
var buf bytes.Buffer
if err := a.Encode(&buf); err != nil {
panic(err)
}
return uint64(len(buf.Bytes()))
}

// We pass 0 here as the type will be overridden when used along with
// the tlv.RecordT type.
return tlv.MakeDynamicRecord(
0, a, sizeFunc, LeafEncoder, LeafDecoder,
)
}

// DecodeRecords provides all records known for an asset witness for proper
// decoding.
func (a *Asset) DecodeRecords() []tlv.Record {
Expand All @@ -1724,7 +1759,7 @@ func (a *Asset) DecodeRecords() []tlv.Record {
NewLeafAmountRecord(&a.Amount),
NewLeafLockTimeRecord(&a.LockTime),
NewLeafRelativeLockTimeRecord(&a.RelativeLockTime),
// We don't need to worry aobut encoding the witness or not
// We don't need to worry about encoding the witness or not
// when we decode, so we just use EncodeNormal here.
NewLeafPrevWitnessRecord(&a.PrevWitnesses, EncodeNormal),
NewLeafSplitCommitmentRootRecord(&a.SplitCommitmentRoot),
Expand Down Expand Up @@ -1793,6 +1828,9 @@ func (a *Asset) Validate() error {
return ValidateAssetName(a.Genesis.Tag)
}

// Ensure Asset implements the tlv.RecordProducer interface.
var _ tlv.RecordProducer = (*Asset)(nil)

// ValidateAssetName validates an asset name (the asset's genesis tag).
func ValidateAssetName(name string) error {
if len(name) == 0 {
Expand Down
7 changes: 0 additions & 7 deletions asset/records.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,6 @@ func NewLeafVersionRecord(version *Version) tlv.Record {
)
}

func NewLeafIDRecord(id *ID) tlv.Record {
const recordSize = sha256.Size
return tlv.MakeStaticRecord(
LeafAssetID, id, recordSize, IDEncoder, IDDecoder,
)
}

func NewLeafGenesisRecord(genesis *Genesis) tlv.Record {
recordSize := func() uint64 {
var (
Expand Down
2 changes: 1 addition & 1 deletion dev.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.21.4 as builder
FROM golang:1.22.3 as builder

WORKDIR /app

Expand Down
11 changes: 11 additions & 0 deletions fn/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,17 @@ func (o Option[A]) UnwrapOrFuncErr(f func() (A, error)) (A, error) {
return f()
}

// UnwrapOrErr is used to extract a value from an option, if the option is
// empty, then the specified error is returned directly.
func (o Option[A]) UnwrapOrErr(err error) (A, error) {
if !o.isSome {
var zero A
return zero, err
}

return o.some, nil
}

// WhenSome is used to conditionally perform a side-effecting function that
// accepts a value of the type that parameterizes the option. If this function
// performs no side effects, WhenSome is useless.
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
module github.com/lightninglabs/taproot-assets

go 1.21.4
go 1.22

toolchain go1.22.2
toolchain go1.22.3

require (
github.com/btcsuite/btcd v0.24.2-beta.rc1.0.20240403021926-ae5533602c46
Expand Down
2 changes: 1 addition & 1 deletion itest/loadtest/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.21.4 as builder
FROM golang:1.22.3 as builder

WORKDIR /app

Expand Down
2 changes: 1 addition & 1 deletion make/builder.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.21.4-bookworm
FROM golang:1.22.3-bookworm

MAINTAINER Olaoluwa Osuntokun <[email protected]>

Expand Down
29 changes: 29 additions & 0 deletions proof/encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,35 @@ import (
"github.com/lightningnetwork/lnd/tlv"
)

// Encoder encodes a proof to the given writer.
func Encoder(w io.Writer, val any, buf *[8]byte) error {
if t, ok := val.(*Proof); ok {
return (*t).Encode(w)
}
return tlv.NewTypeForEncodingErr(val, "Proof")
}

// Decoder decodes a proof from the given reader.
func Decoder(r io.Reader, val any, buf *[8]byte, l uint64) error {
if l > FileMaxProofSizeBytes {
return tlv.ErrRecordTooLarge
}
if typ, ok := val.(*Proof); ok {
var proofBytes []byte
if err := tlv.DVarBytes(r, &proofBytes, buf, l); err != nil {
return err
}
var proof Proof
err := proof.Decode(bytes.NewReader(proofBytes))
if err != nil {
return err
}
*typ = proof
return nil
}
return tlv.NewTypeForEncodingErr(val, "Proof")
}

func VersionEncoder(w io.Writer, val any, buf *[8]byte) error {
if t, ok := val.(*TransitionVersion); ok {
return tlv.EUint32T(w, uint32(*t), buf)
Expand Down
30 changes: 19 additions & 11 deletions proof/mint.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,19 +294,27 @@ func baseProof(params *BaseProofParams, prevOut wire.OutPoint) (*Proof, error) {
// coreProof creates the basic proof template that contains only fields
// dependent on anchor transaction confirmation.
func coreProof(params *BaseProofParams) (*Proof, error) {
merkleProof, err := NewTxMerkleProof(
params.Block.Transactions, params.TxIndex,
)
if err != nil {
return nil, fmt.Errorf("unable to create merkle proof: %w", err)
cProof := &Proof{
BlockHeader: params.Block.Header,
BlockHeight: params.BlockHeight,
}

if params.Tx != nil {
var err error
cProof.AnchorTx = *params.Tx

merkleProof, err := NewTxMerkleProof(
params.Block.Transactions, params.TxIndex,
)
if err != nil {
return nil, fmt.Errorf("unable to create merkle "+
"proof: %w", err)
}

cProof.TxMerkleProof = *merkleProof
}

return &Proof{
BlockHeader: params.Block.Header,
BlockHeight: params.BlockHeight,
AnchorTx: *params.Tx,
TxMerkleProof: *merkleProof,
}, nil
return cProof, nil
}

// committedProofs creates a map of proofs, keyed by the script key of each of
Expand Down
22 changes: 22 additions & 0 deletions proof/proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,25 @@ func (p *Proof) Decode(r io.Reader) error {
return stream.Decode(r)
}

// Record returns a TLV record that can be used to encode/decode a Proof to/from
// a TLV stream.
//
// NOTE: This is part of the tlv.RecordProducer interface.
func (p *Proof) Record() tlv.Record {
sizeFunc := func() uint64 {
var buf bytes.Buffer
err := p.Encode(&buf)
if err != nil {
panic(err)
}
return uint64(len(buf.Bytes()))
}

// Note that we set the type here as zero, as when used with a
// tlv.RecordT, the type param will be used as the type.
return tlv.MakeDynamicRecord(0, p, sizeFunc, Encoder, Decoder)
}

// IsUnknownVersion returns true if a proof has a version that is not recognized
// by this implementation of tap.
func (p *Proof) IsUnknownVersion() bool {
Expand All @@ -441,6 +460,9 @@ func (p *Proof) IsUnknownVersion() bool {
}
}

// Ensure Proof implements the tlv.RecordProducer interface.
var _ tlv.RecordProducer = (*Proof)(nil)

// SparseDecode can be used to decode a proof from a reader without decoding
// and parsing the entire thing. This handles ignoring the magic bytes, and
// will decode directly into the target records.
Expand Down
15 changes: 9 additions & 6 deletions rpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,9 @@ func (r *rpcServer) fetchRpcAssets(ctx context.Context, withWitness,

rpcAssets := make([]*taprpc.Asset, len(assets))
for i, a := range assets {
rpcAssets[i], err = r.marshalChainAsset(ctx, a, withWitness)
rpcAssets[i], err = MarshalChainAsset(
ctx, a, withWitness, r.cfg.AddrBook,
)
if err != nil {
return nil, fmt.Errorf("unable to marshal asset: %w",
err)
Expand All @@ -821,11 +823,12 @@ func (r *rpcServer) fetchRpcAssets(ctx context.Context, withWitness,
return rpcAssets, nil
}

func (r *rpcServer) marshalChainAsset(ctx context.Context, a *asset.ChainAsset,
withWitness bool) (*taprpc.Asset, error) {
// MarshalChainAsset marshals the given chain asset into an RPC asset.
func MarshalChainAsset(ctx context.Context, a *asset.ChainAsset,
withWitness bool, keyRing taprpc.KeyLookup) (*taprpc.Asset, error) {

rpcAsset, err := taprpc.MarshalAsset(
ctx, a.Asset, a.IsSpent, withWitness, r.cfg.AddrBook,
ctx, a.Asset, a.IsSpent, withWitness, keyRing,
)
if err != nil {
return nil, err
Expand Down Expand Up @@ -1496,7 +1499,7 @@ func (r *rpcServer) marshalProof(ctx context.Context, p *proof.Proof,
}
}

rpcAsset, err := r.marshalChainAsset(ctx, &asset.ChainAsset{
rpcAsset, err := MarshalChainAsset(ctx, &asset.ChainAsset{
Asset: &p.Asset,
AnchorTx: &p.AnchorTx,
AnchorBlockHash: p.BlockHeader.BlockHash(),
Expand All @@ -1505,7 +1508,7 @@ func (r *rpcServer) marshalProof(ctx context.Context, p *proof.Proof,
AnchorInternalKey: p.InclusionProof.InternalKey,
AnchorMerkleRoot: merkleRoot[:],
AnchorTapscriptSibling: tsSibling,
}, withPrevWitnesses)
}, withPrevWitnesses, r.cfg.AddrBook)
if err != nil {
return nil, err
}
Expand Down
Loading

0 comments on commit 91a51d6

Please sign in to comment.