|
1 | 1 | package supplycommit |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "bytes" |
4 | 5 | "context" |
5 | 6 | "errors" |
6 | 7 | "fmt" |
7 | 8 |
|
| 9 | + "github.com/btcsuite/btcd/wire" |
8 | 10 | "github.com/lightninglabs/taproot-assets/address" |
9 | 11 | "github.com/lightninglabs/taproot-assets/asset" |
| 12 | + "github.com/lightninglabs/taproot-assets/proof" |
| 13 | + "github.com/lightninglabs/taproot-assets/tapgarden" |
10 | 14 | "github.com/lightningnetwork/lnd/fn/v2" |
11 | 15 | ) |
12 | 16 |
|
@@ -163,3 +167,68 @@ func IsSupplySupported(ctx context.Context, assetLookup AssetLookup, |
163 | 167 |
|
164 | 168 | return true, nil |
165 | 169 | } |
| 170 | + |
| 171 | +// ExtractSupplyLeavesBlockHeaders is a helper method which extracts the block |
| 172 | +// headers from the supply leaves. The returned map is keyed by block height. |
| 173 | +func ExtractSupplyLeavesBlockHeaders(ctx context.Context, |
| 174 | + chain tapgarden.ChainBridge, |
| 175 | + supplyLeaves SupplyLeaves) (map[uint32]wire.BlockHeader, error) { |
| 176 | + |
| 177 | + blockHeaders := make(map[uint32]wire.BlockHeader) |
| 178 | + |
| 179 | + // Extract block headers from issuance leaves. |
| 180 | + for idx := range supplyLeaves.IssuanceLeafEntries { |
| 181 | + leaf := supplyLeaves.IssuanceLeafEntries[idx] |
| 182 | + |
| 183 | + // Sparse decode the block header from the issuance proof. |
| 184 | + var blockHeader wire.BlockHeader |
| 185 | + err := proof.SparseDecode( |
| 186 | + bytes.NewReader(leaf.IssuanceProof.RawProof), |
| 187 | + proof.BlockHeaderRecord(&blockHeader), |
| 188 | + ) |
| 189 | + if err != nil { |
| 190 | + return nil, fmt.Errorf("unable to sparse decode "+ |
| 191 | + "block header from proof: %w", err) |
| 192 | + } |
| 193 | + |
| 194 | + blockHeaders[leaf.BlockHeight()] = blockHeader |
| 195 | + } |
| 196 | + |
| 197 | + // Extract block headers from burn leaves. |
| 198 | + for idx := range supplyLeaves.BurnLeafEntries { |
| 199 | + leaf := supplyLeaves.BurnLeafEntries[idx] |
| 200 | + |
| 201 | + if leaf.BurnProof == nil { |
| 202 | + return nil, fmt.Errorf("burn proof is nil for burn " + |
| 203 | + "leaf") |
| 204 | + } |
| 205 | + |
| 206 | + blockHeader := leaf.BurnProof.BlockHeader |
| 207 | + blockHeaders[leaf.BlockHeight()] = blockHeader |
| 208 | + } |
| 209 | + |
| 210 | + // Extract block headers from ignore leaves. |
| 211 | + for idx := range supplyLeaves.IgnoreLeafEntries { |
| 212 | + leaf := supplyLeaves.IgnoreLeafEntries[idx] |
| 213 | + blockHeight := leaf.BlockHeight() |
| 214 | + |
| 215 | + // If we already have the block header for this height, skip |
| 216 | + // fetching it again from the chain backend. |
| 217 | + if _, ok := blockHeaders[blockHeight]; ok { |
| 218 | + continue |
| 219 | + } |
| 220 | + |
| 221 | + blockHeader, err := chain.GetBlockHeaderByHeight( |
| 222 | + ctx, int64(blockHeight), |
| 223 | + ) |
| 224 | + if err != nil { |
| 225 | + return nil, fmt.Errorf("unable to fetch block "+ |
| 226 | + "header at height %d: %w", |
| 227 | + blockHeight, err) |
| 228 | + } |
| 229 | + |
| 230 | + blockHeaders[blockHeight] = *blockHeader |
| 231 | + } |
| 232 | + |
| 233 | + return blockHeaders, nil |
| 234 | +} |
0 commit comments