Digital MRV (dMRV) is measurement, reporting and verification done with devices and signed records instead of periodic surveys. Devices collect data continuously, a protocol says what counts, the data is checked against the protocol's rules, and a verified result is issued as a credential that others can check. Each record is anchored on chain, so it cannot be changed without that showing.
This page shows the technical parts of such a system, in order, with the shape of each record: the architecture, the protocol, device data, the data pipeline, verification, the claim and the credential, then an integration example and the error codes. To plan a dMRV workflow on paper first, use Design a digital MRV workflow.
Illustrative example. The JSON, Python and JavaScript on this page show the shape of each record and call. They are not a tested sequence you can run as written.
Architecture
A dMRV system has four layers.
| Layer | What it does |
|---|---|
| Data collection | IoT devices and sensors capture measurements in real time |
| Data validation | Oracle services check the data's integrity and accuracy |
| Blockchain storage | An unchangeable record of verified measurements |
| Credential issuance | Certification of verified claims, without manual steps |
Validation covers data format compliance, value range checks, cross-reference validation and temporal consistency.
Configure the protocol
A protocol is the template a project measures against.
| Task | What to do |
|---|---|
| Project setup | Select or create a protocol template. Define the measurement parameters. Configure the validation rules. Set the reporting intervals. |
| Methodology alignment | Map the protocol to recognised standards. Set the baseline calculations. Define the emission factors. Configure the verification rules. |
Example protocol
{
"type": "CleanCookingProtocol",
"version": "1.0.0",
"methodology": "GS_MMECD_1.0",
"parameters": {
"measurementInterval": 300,
"requiredMetrics": [
"burnTime",
"fuelConsumed",
"temperature"
],
"baselineEmissionFactor": 7.2,
"minimumDataPoints": 100
},
"validation": {
"rules": [{
"metric": "temperature",
"min": 50,
"max": 300
}],
"requiredEvidence": [
"deviceTelemetry",
"fuelDelivery",
"baselineData"
]
}
}Collect device data
Device integration
from emerging import Device, Protocol
# Load protocol
protocol = Protocol.get("clean-cooking-v1")
# Configure device with protocol
device = Device.configure(
device_id="did:ixo:device/123",
protocol=protocol,
settings={
"measurement_interval": 300,
"offline_buffer_size": 1000
}
)
# Start measurements
device.start_monitoring(){
"deviceId": "did:ixo:device/123",
"timestamp": "2024-03-15T12:00:00Z",
"measurements": {
"burnTime": 300,
"fuelConsumed": 15,
"temperature": 180
},
"signature": "0xabc..."
}Data pipeline
| Stage | What happens |
|---|---|
| Collection | Device authentication, secure data transmission, edge validation, offline buffering |
| Processing | Protocol validation, data aggregation, anomaly detection, baseline comparison |
Verify the measurements
An oracle checks the measurements against the protocol and the evidence. On IXO, a decision oracle produces facts and the IXO decision engine applies the rules and signs the decision. See Decision oracle.
from emerging import Oracle, Protocol
# Initialize oracle with protocol
oracle = Oracle(
protocol_id="clean-cooking-v1",
min_confidence=0.95,
required_validators=3
)
# Verify measurements
verification = oracle.verify_measurements(
measurements=device_data,
baseline=baseline_data,
evidence={
"telemetry": sensor_logs,
"delivery": fuel_records
}
)
# Issue credential if valid
if verification.is_valid:
credential = verification.issue_credential()import { Oracle, Protocol } from '@emerging/sdk';
// Initialize oracle with protocol
const oracle = new Oracle({
protocolId: 'clean-cooking-v1',
minConfidence: 0.95,
requiredValidators: 3
});
// Verify measurements
const verification = await oracle.verifyMeasurements({
measurements: deviceData,
baseline: baselineData,
evidence: {
telemetry: sensorLogs,
delivery: fuelRecords
}
});
// Issue credential if valid
if (verification.isValid) {
const credential = await verification.issueCredential();
}Validation rules
The measurements follow the protocol specification
The cryptographic proofs are valid
A confidence score for the supporting evidence
Claim structure
A measurement claim has these fields.
Type of measurement claim
DID of measuring device
Key-value pairs of measurements
Supporting data and proofs
Issue the credential
A verified result is issued as a verifiable credential. A credential shows who signed what. It is not proof that the measurement is true: see What each record proves.
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/dmrv/v1"
],
"type": ["VerifiableCredential", "MeasurementClaim"],
"issuer": "did:ixo:oracle/456",
"issuanceDate": "2024-03-15T12:00:00Z",
"credentialSubject": {
"id": "did:ixo:device/123",
"protocol": "clean-cooking-v1",
"measurements": {
"burnTime": 300,
"fuelConsumed": 15
},
"evidence": [{
"type": "TelemetryData",
"hash": "0x123...",
"uri": "ipfs://Qm..."
}]
}
}Integration example
The whole sequence in one place: collect measurements from a device, verify them with an oracle and issue a credential when they are valid.
from emerging import Device, Oracle, Credential
# Initialize device and oracle
device = Device("did:ixo:device/123")
oracle = Oracle("did:ixo:oracle/456")
# Collect and verify measurements
measurements = device.collect_measurements()
verification = oracle.verify_measurements(measurements)
# Issue verified credential
if verification.is_valid:
credential = Credential.issue(
type="MeasurementClaim",
subject=measurements,
evidence=verification.proof
)import { Device, Oracle, Credential } from '@emerging/sdk';
// Initialize device and oracle
const device = new Device('did:ixo:device/123');
const oracle = new Oracle('did:ixo:oracle/456');
// Collect and verify measurements
const measurements = await device.collectMeasurements();
const verification = await oracle.verifyMeasurements(measurements);
// Issue verified credential
if (verification.isValid) {
const credential = await Credential.issue({
type: 'MeasurementClaim',
subject: measurements,
evidence: verification.proof
});
}Error codes
| Code | Meaning |
|---|---|
400 | Invalid measurement format |
401 | Unauthorized device or oracle |
409 | Conflicting measurements |
Practices
Follow the protocol specification closely, and validate data at every stage.
| Area | Practices |
|---|---|
| Security | Use secure communication channels. Implement device authentication. Validate data integrity. Monitor for anomalies. |
| Scale | Configure offline buffering. Implement batch processing. Use load balancing. Monitor system performance. |