blueprint-tangle-extra
Producer/Consumer extras for Tangle (v2) blueprints with BLS signature aggregation support.
Overview
This crate provides the infrastructure for building blueprints that interact with Tangle v2 EVM contracts, including:
- TangleProducer: Polls for
JobSubmittedevents and streams job calls - TangleConsumer: Submits individual job results via
submitResult - AggregatingConsumer: Aggregates BLS signatures and submits via
submitAggregatedResult - AggregationStrategy: Choose between HTTP service or P2P gossip for signature aggregation
Features
| Feature | Description |
|---|---|
std (default) |
Standard library support |
aggregation |
HTTP-based aggregation service client |
p2p-aggregation |
Peer-to-peer gossip-based aggregation |
Quick Start
Basic Blueprint (No Aggregation)
use BlueprintRunner;
use ;
async
With BLS Aggregation (HTTP Service)
use ;
let consumer = new
.with_aggregation_strategy;
With BLS Aggregation (P2P Gossip)
use ;
use HashMap;
// Discover operator BLS public keys (from on-chain registration)
let participant_keys: =
discover_operator_keys.await?;
// Count-based threshold (67% of operators must sign)
let p2p_config = new
.with_threshold_percentage;
let consumer = new
.with_aggregation_strategy;
Threshold Types
The aggregation system supports two threshold types that match the on-chain Types.ThresholdType:
Count-Based (Default)
Each operator has equal weight (1). Threshold is a percentage of operator count.
// 67% of operators must sign
let config = new
.with_threshold_percentage;
// Or using basis points (matches on-chain format):
let config = new
.with_threshold_bps // 67.00%
.with_threshold_type;
Stake-Weighted
Operators are weighted by their stake exposure (ServiceOperator.exposureBps from the contract).
// Query operator weights from chain (exposureBps values)
let operator_weights: = from;
// 75% of total stake must sign
let config = new
.with_stake_weighted_threshold;
P2PGossipConfig API
| Method | Description |
|---|---|
new(handle, keys) |
Create with defaults (67% count-based) |
with_threshold_percentage(u8) |
Set threshold as percentage (0-100) |
with_threshold_bps(u16) |
Set threshold in basis points (0-10000) |
with_threshold_type(ThresholdType) |
Set explicit threshold type |
with_operator_weights(HashMap) |
Set operator weights for stake-weighted |
with_stake_weighted_threshold(bps, weights) |
Convenience for stake-weighted setup |
with_timeout(Duration) |
Protocol timeout (default: 30s) |
with_num_aggregators(u16) |
Number of aggregator nodes (default: 2) |
On-Chain Integration
The threshold configuration comes from your BlueprintServiceManager contract:
function getAggregationThreshold(uint64 serviceId, uint8 jobIndex)
external view returns (uint16 thresholdBps, uint8 thresholdType);
// thresholdBps: e.g., 6700 = 67%
// thresholdType: 0 = CountBased, 1 = StakeWeighted
The AggregatingConsumer queries this to determine how to aggregate signatures, then submits the result via:
function submitAggregatedResult(
uint64 serviceId,
uint64 callId,
bytes calldata output,
uint256 signerBitmap,
uint256[2] calldata aggregatedSignature,
uint256[4] calldata aggregatedPubkey
) external;
Architecture
┌─────────────────┐
│ Job Submitted │
│ (on-chain) │
└────────┬────────┘
│
┌────────▼────────┐
│ TangleProducer │
└────────┬────────┘
│
┌────────▼────────┐
│ Blueprint Job │
│ Handler │
└────────┬────────┘
│
┌──────────────┴──────────────┐
│ │
┌─────────▼─────────┐ ┌────────▼────────┐
│ TangleConsumer │ │AggregatingConsumer│
│ (single result) │ │ (BLS aggregated) │
└─────────┬─────────┘ └────────┬────────┘
│ │
│ ┌───────────┴───────────┐
│ │ │
│ ┌─────────▼─────────┐ ┌────────▼────────┐
│ │ HTTP Service │ │ P2P Gossip │
│ │ Aggregation │ │ Aggregation │
│ └─────────┬─────────┘ └────────┬────────┘
│ │ │
│ └───────────┬───────────┘
│ │
┌─────────▼─────────┐ ┌────────▼────────┐
│ submitResult │ │submitAggregated │
│ (on-chain) │ │ (on-chain) │
└───────────────────┘ └─────────────────┘
License
Licensed under the Apache License, Version 2.0.