Blueprint Pricing
This guide explains how pricing works for blueprint execution and how to integrate pricing functionality into your applications that use Tangle Network blueprints.
Prerequisites
- Understanding of Blueprint concepts and execution model
- Familiarity with Tangle Network architecture
- Basic knowledge of cryptographic signatures and verification
Pricing Workflow
The complete workflow for getting quotes and executing blueprints consists of:
-
Finding Operators: Retrieve all operators registered for the blueprint to be executed.
-
Requesting Quotes: Request price quotes from operators:
- Generate a proof-of-work for the request
- Create a properly formatted price request
- Submit the request via gRPC (at the address specified by each operator on-chain)
-
Processing Quotes: When you receive quotes from operators:
- Verify their signatures
- Validate the proof-of-work
- Compare prices
-
Selecting Operators: Choose which operators to use based on their pricing quotes, typically selecting the most cost-effective options.
-
Submitting Request: Submit an on-chain request that includes your selected quotes via the
request_with_signed_price_quotes
services extrinsic. -
Blueprint Execution: The selected operators will execute the blueprint according to the agreed terms.
Pricing API
To request price quotes, your application will use the gRPC API provided by operators. You just need to send a GetPrice
gRPC request to the operator’s gRPC endpoint. Here’s the service definition in protobuf:
// The pricing service definition
service Pricing {
// Retrieves a signed price quote for a given blueprint
rpc GetPrice (GetPriceRequest) returns (GetPriceResponse);
}
Message Types
Here are the key message types you’ll work with:
// The pricing service definition
service PricingEngine {
// Retrieves a signed price quote for a given blueprint
rpc GetPrice (GetPriceRequest) returns (GetPriceResponse);
}
// Asset type enumeration
enum AssetType {
CUSTOM = 0;
ERC20 = 1;
}
// Asset type definition
message Asset {
oneof asset_type {
// Custom asset with a numeric identifier
uint64 custom = 1;
// ERC20 token with an H160 address
bytes erc20 = 2;
}
}
// Security requirements for an asset
message AssetSecurityRequirements {
// The asset type
Asset asset = 1;
// Minimum exposure percentage (0-100)
uint32 minimum_exposure_percent = 2;
// Maximum exposure percentage (0-100)
uint32 maximum_exposure_percent = 3;
}
// Security commitment for an asset
message AssetSecurityCommitment {
// The asset type
Asset asset = 1;
// Committed exposure percentage (0-100)
uint32 exposure_percent = 2;
}
// Resource requirement for a specific resource type
message ResourceRequirement {
// Resource kind (CPU, Memory, GPU, etc.)
string kind = 1;
// Quantity required
uint64 count = 2;
}
// Pricing for a specific resource type
message ResourcePricing {
// Resource kind (CPU, Memory, GPU, etc.)
string kind = 1;
// Quantity of the resource
uint64 count = 2;
// Price per unit in USD with decimal precision
double price_per_unit_rate = 3;
}
// Request message for GetPrice RPC
message GetPriceRequest {
// The blueprint ID
uint64 blueprint_id = 1;
// Time-to-live for service in blocks
uint64 ttl_blocks = 2;
// Proof of work to prevent DDOS
bytes proof_of_work = 3;
// Optional resource recommendations
repeated ResourceRequirement resource_requirements = 4;
// Security requirements for assets
AssetSecurityRequirements security_requirements = 5;
}
// Response message for GetPrice RPC
message GetPriceResponse {
// The quote details
QuoteDetails quote_details = 1;
// Signature of the hash of the body
bytes signature = 2;
// Operator ID
bytes operator_id = 3;
// Proof of work response
bytes proof_of_work = 4;
}
// The detailed quote information
message QuoteDetails {
// The blueprint ID
uint64 blueprint_id = 1;
// Time-to-live for service in blocks
uint64 ttl_blocks = 2;
// Total cost in USD with decimal precision
double total_cost_rate = 3;
// Timestamp when quote was generated
uint64 timestamp = 4;
// Expiry timestamp
uint64 expiry = 5;
// Resource pricing details
repeated ResourcePricing resources = 6;
// Security commitments for assets
AssetSecurityCommitment security_commitments = 7;
}
Implementation Steps
1. Generating Proof-of-Work
Before requesting a quote, you need to generate a valid proof-of-work for the request. The Operator pricing server uses the Equix Equihash Rust implementation for proof-of-work generation.
2. Creating and sending a Price Request
Next, create a price request with your requirements using the types defined in Message Types and send it to each operator registered to the blueprint you want to run. Both the registered operators and their gRPC endpoints are available on-chain.
3. Verifying Quote Signatures
When you receive quotes, verify their authenticity by using the hash of the quote details and the operator’s signature of the quote’s hash that was included in the response.
4. Selecting Operators
After verifying the quotes, select the operators you want to use based on their pricing and security commitments. It is recommended to automatically select the lowest-priced operators.
5. Requesting service with quotes
After selecting the operators, submit your request to the blockchain using the request_with_signed_price_quotes
services extrinsic with the selected operators and their quotes.
Understanding Pricing Calculations
Operators calculate prices using this formula:
Price = Resource Cost × Duration Factor × Security Factor
This means that the total cost of a blueprint execution is the sum of the prices from all selected operators.
Where:
- Resource Cost = resource_count × price_per_unit_rate
- Duration Factor = time_blocks × BLOCK_TIME
- Security Factor = Factor based on security requirements
Understanding this helps you estimate costs and evaluate quotes effectively.
Best Practices
- Get Multiple Quotes: Always request quotes from all registered operators to compare prices
- Verify All Signatures: Always verify the signature of each quote before using it
- Check Expiry Times: Ensure quotes haven’t expired before submitting them to the blockchain
- Include Complete Security Requirements: Specify all necessary security parameters in your requests
- Handle Errors Gracefully: Implement proper error handling for failed quote requests
- Keep Quotes Intact: Never modify quote details after receiving them
- Use Fresh Proof-of-Work: Generate a new proof-of-work for each request
- Expect Price Variation: Don’t assume all operators will provide the same price