Skip to content

Commit 0dfdb12

Browse files
authored
Merge pull request #1050 from lightninglabs/proof_decode_read_metareveal
taprpc: marshal with metareveal of issuance proof
2 parents 054a66c + 21c1148 commit 0dfdb12

File tree

6 files changed

+93
-23
lines changed

6 files changed

+93
-23
lines changed

itest/assertions.go

+9
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,15 @@ func AssetVersionCheck(version taprpc.AssetVersion) AssetCheck {
233233
// non-nil decimal display value.
234234
func AssetDecimalDisplayCheck(decDisplay uint32) AssetCheck {
235235
return func(a *taprpc.Asset) error {
236+
// If we didn't set a decimal display in the mint request, we
237+
// don't expect one to be set.
238+
if decDisplay == 0 &&
239+
(a.DecimalDisplay == nil ||
240+
a.DecimalDisplay.DecimalDisplay == 0) {
241+
242+
return nil
243+
}
244+
236245
if a.DecimalDisplay == nil {
237246
return fmt.Errorf("asset decimal display is nil")
238247
}

proof/meta.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -182,13 +182,13 @@ func DecodeMetaJSON(jBytes []byte) (map[string]interface{}, error) {
182182
// These bytes must match our metadata size constraints.
183183
err := IsValidMetaSize(jBytes, MetaDataMaxSizeBytes)
184184
if err != nil {
185-
return nil, err
185+
return nil, fmt.Errorf("%w: %s", ErrInvalidJSON, err.Error())
186186
}
187187

188188
// Unmarshal checks internally if the JSON is valid.
189189
err = json.Unmarshal(jBytes, &jMeta)
190190
if err != nil {
191-
return nil, err
191+
return nil, fmt.Errorf("%w: %s", ErrInvalidJSON, err.Error())
192192
}
193193

194194
return jMeta, nil

proof/meta_test.go

+37
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,25 @@
11
package proof
22

33
import (
4+
"bytes"
5+
"encoding/hex"
6+
"os"
7+
"path/filepath"
8+
"strings"
49
"testing"
510

611
"github.com/stretchr/testify/require"
712
)
813

14+
var (
15+
// proofInvalidJsonHexFileName is the name of the file that contains the
16+
// hex proof data for a proof where the meta type is declared as JSON
17+
// but the data is not valid JSON.
18+
proofInvalidJsonHexFileName = filepath.Join(
19+
testDataFileName, "proof-invalid-json-meta-reveal.hex",
20+
)
21+
)
22+
923
func TestValidateMetaReveal(t *testing.T) {
1024
t.Parallel()
1125

@@ -78,3 +92,26 @@ func TestValidateMetaReveal(t *testing.T) {
7892
})
7993
}
8094
}
95+
96+
// TestProofInvalidJsonMetaReveal tests that a proof with a meta reveal that
97+
// is declared as JSON but is not valid JSON will return the correct error when
98+
// trying to decode the decimal display.
99+
func TestProofInvalidJsonMetaReveal(t *testing.T) {
100+
proofHex, err := os.ReadFile(proofInvalidJsonHexFileName)
101+
require.NoError(t, err)
102+
103+
proofBytes, err := hex.DecodeString(
104+
strings.Trim(string(proofHex), "\n"),
105+
)
106+
require.NoError(t, err)
107+
108+
p := &Proof{}
109+
err = p.Decode(bytes.NewReader(proofBytes))
110+
require.NoError(t, err)
111+
112+
require.NotNil(t, p.MetaReveal)
113+
114+
_, decDisplay, err := p.MetaReveal.GetDecDisplay()
115+
require.ErrorIs(t, err, ErrInvalidJSON)
116+
require.Zero(t, decDisplay)
117+
}

proof/testdata/proof-invalid-json-meta-reveal.hex

+1
Large diffs are not rendered by default.

rpcserver.go

+43-20
Original file line numberDiff line numberDiff line change
@@ -1035,7 +1035,7 @@ func (r *rpcServer) fetchRpcAssets(ctx context.Context, withWitness,
10351035
rpcAssets := make([]*taprpc.Asset, len(assets))
10361036
for i, a := range assets {
10371037
rpcAssets[i], err = r.MarshalChainAsset(
1038-
ctx, a, withWitness, r.cfg.AddrBook,
1038+
ctx, a, nil, withWitness, r.cfg.AddrBook,
10391039
)
10401040
if err != nil {
10411041
return nil, fmt.Errorf("unable to marshal asset: %w",
@@ -1048,16 +1048,28 @@ func (r *rpcServer) fetchRpcAssets(ctx context.Context, withWitness,
10481048

10491049
// MarshalChainAsset marshals the given chain asset into an RPC asset.
10501050
func (r *rpcServer) MarshalChainAsset(ctx context.Context, a *asset.ChainAsset,
1051-
withWitness bool, keyRing taprpc.KeyLookup) (*taprpc.Asset, error) {
1051+
meta *proof.MetaReveal, withWitness bool,
1052+
keyRing taprpc.KeyLookup) (*taprpc.Asset, error) {
10521053

1053-
decDisplay, err := r.DecDisplayForAssetID(ctx, a.ID())
1054+
var (
1055+
decDisplay fn.Option[uint32]
1056+
err error
1057+
)
1058+
1059+
// If the asset metadata is provided, we don't need to look it up from
1060+
// the database when decoding a decimal display value.
1061+
switch {
1062+
case meta != nil:
1063+
decDisplay, err = getDecimalDisplayNonStrict(meta)
1064+
default:
1065+
decDisplay, err = r.DecDisplayForAssetID(ctx, a.ID())
1066+
}
10541067
if err != nil {
10551068
return nil, err
10561069
}
10571070

10581071
rpcAsset, err := taprpc.MarshalAsset(
1059-
ctx, a.Asset, a.IsSpent, withWitness, keyRing,
1060-
fn.Some(decDisplay),
1072+
ctx, a.Asset, a.IsSpent, withWitness, keyRing, decDisplay,
10611073
)
10621074
if err != nil {
10631075
return nil, err
@@ -1748,7 +1760,7 @@ func (r *rpcServer) marshalProof(ctx context.Context, p *proof.Proof,
17481760
AnchorInternalKey: p.InclusionProof.InternalKey,
17491761
AnchorMerkleRoot: merkleRoot[:],
17501762
AnchorTapscriptSibling: tsSibling,
1751-
}, withPrevWitnesses, r.cfg.AddrBook)
1763+
}, p.MetaReveal, withPrevWitnesses, r.cfg.AddrBook)
17521764
if err != nil {
17531765
return nil, err
17541766
}
@@ -4997,7 +5009,7 @@ func (r *rpcServer) AssetLeaves(ctx context.Context,
49975009
}
49985010

49995011
resp.Leaves[i], err = r.marshalAssetLeaf(
5000-
ctx, &assetLeaf, fn.Some(decDisplay),
5012+
ctx, &assetLeaf, decDisplay,
50015013
)
50025014
if err != nil {
50035015
return nil, err
@@ -5100,9 +5112,7 @@ func (r *rpcServer) marshalUniverseProofLeaf(ctx context.Context,
51005112
return nil, err
51015113
}
51025114

5103-
assetLeaf, err := r.marshalAssetLeaf(
5104-
ctx, proof.Leaf, fn.Some(decDisplay),
5105-
)
5115+
assetLeaf, err := r.marshalAssetLeaf(ctx, proof.Leaf, decDisplay)
51065116
if err != nil {
51075117
return nil, err
51085118
}
@@ -5519,7 +5529,7 @@ func (r *rpcServer) marshalUniverseDiff(ctx context.Context,
55195529
}
55205530

55215531
leaves[i], err = r.marshalAssetLeaf(
5522-
ctx, leaf, fn.Some(decDisplay),
5532+
ctx, leaf, decDisplay,
55235533
)
55245534
if err != nil {
55255535
return err
@@ -5603,8 +5613,8 @@ func marshalUniverseServer(
56035613
// of the local Universe server. These servers are used to push out new proofs,
56045614
// and also periodically call sync new proofs from the remote server.
56055615
func (r *rpcServer) ListFederationServers(ctx context.Context,
5606-
_ *unirpc.ListFederationServersRequest,
5607-
) (*unirpc.ListFederationServersResponse, error) {
5616+
_ *unirpc.ListFederationServersRequest) (
5617+
*unirpc.ListFederationServersResponse, error) {
56085618

56095619
uniServers, err := r.cfg.FederationDB.UniverseServers(ctx)
56105620
if err != nil {
@@ -6791,30 +6801,43 @@ func encodeVirtualPackets(packets []*tappsbt.VPacket) ([][]byte, error) {
67916801
// DecDisplayForAssetID attempts to fetch the meta reveal for a specific asset
67926802
// ID and extract the decimal display value from it.
67936803
func (r *rpcServer) DecDisplayForAssetID(ctx context.Context,
6794-
id asset.ID) (uint32, error) {
6804+
id asset.ID) (fn.Option[uint32], error) {
67956805

67966806
meta, err := r.cfg.AssetStore.FetchAssetMetaForAsset(
67976807
ctx, id,
67986808
)
67996809
if err != nil {
6800-
return 0, fmt.Errorf("unable to fetch asset meta "+
6801-
"for asset_id=%v :%v", id, err)
6810+
return fn.None[uint32](), fmt.Errorf("unable to fetch asset "+
6811+
"meta for asset_id=%v :%v", id, err)
68026812
}
68036813

6814+
return getDecimalDisplayNonStrict(meta)
6815+
}
6816+
6817+
// getDecimalDisplayNonStrict attempts to decode a decimal display value from
6818+
// metadata. If no custom decimal display value is decoded, the default value of
6819+
// 0 is returned without error.
6820+
func getDecimalDisplayNonStrict(
6821+
meta *proof.MetaReveal) (fn.Option[uint32], error) {
6822+
68046823
_, decDisplay, err := meta.GetDecDisplay()
68056824
switch {
68066825
// If it isn't JSON, or doesn't have a dec display, we'll just return 0
68076826
// below.
68086827
case errors.Is(err, proof.ErrNotJSON):
68096828
fallthrough
6829+
case errors.Is(err, proof.ErrInvalidJSON):
6830+
fallthrough
68106831
case errors.Is(err, proof.ErrDecDisplayMissing):
68116832
fallthrough
68126833
case errors.Is(err, proof.ErrDecDisplayInvalidType):
6813-
break
6834+
// We can't determine if there is a decimal display value set.
6835+
return fn.None[uint32](), nil
6836+
68146837
case err != nil:
6815-
return 0, fmt.Errorf("unable to extract decimal "+
6816-
"display for asset_id=%v :%v", id, err)
6838+
return fn.None[uint32](), fmt.Errorf("unable to extract "+
6839+
"decimal display: %v", err)
68176840
}
68186841

6819-
return decDisplay, nil
6842+
return fn.Some(decDisplay), nil
68206843
}

version.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const (
4545
AppMinor uint = 4
4646

4747
// AppPatch defines the application patch for this binary.
48-
AppPatch uint = 0
48+
AppPatch uint = 1
4949

5050
// AppStatus defines the release status of this binary (e.g. beta).
5151
AppStatus = "alpha"

0 commit comments

Comments
 (0)