Skip to content

CIP-0180? | Block Producer Identification#1157

Open
disassembler wants to merge 1 commit intocardano-foundation:masterfrom
disassembler:sl-ad/block-producer-id
Open

CIP-0180? | Block Producer Identification#1157
disassembler wants to merge 1 commit intocardano-foundation:masterfrom
disassembler:sl-ad/block-producer-id

Conversation

@disassembler
Copy link
Copy Markdown
Contributor

@disassembler disassembler commented Mar 5, 2026

Summary

This CIP proposes adding a new optional block producer identification element to Cardano blocks in the Dijkstra era:

Block Producer Identification: A free-form text field (1–32 bytes) wrapped in an extensible informational_data_set array added as the 6th element of the block body, allowing block
producers to identify their node implementation and version, similar to HTTP user-agent strings.

Motivation

With multiple node implementations entering block production (cardano-node, Amaru, Dingo, Torsten, Gerolamo), the ecosystem needs visibility into implementation diversity, upgrade
progress, and network resilience through historical block analysis. Build metadata notation (e.g., +leios, +peras) enables tracking experimental feature deployment on testnets.

Key Features

  • 32-byte maximum matching Ethereum graffiti precedent
  • Block body placement — header remains unchanged
  • informational_data_set wrapper for future extensibility (additional fields can be appended without a new era boundary)
  • Minimum string length of 1 byte (nil already handles opt-out)
  • Optional (nil) preserving operator privacy
  • Purely informational — does not affect consensus
  • Implementation-agnostic specification via Cardano Blueprint

New Era Required

This proposal requires a new era as it modifies block CBOR serialization:

  • Block structure: 5 → 6 elements
  • Header: Unchanged
  • Block body hash computation includes new 6th element
  • Target era: Dijkstra

Technical Details

  CDDL:
  block =
    [ header
    , transaction_bodies
    , transaction_witness_sets
    , auxiliary_data_set
    , invalid_transactions
    , informational_data_set / nil  ; NEW
    ]

  informational_data_set =
    [ producer_agent : tstr .size (1..32) / nil ]

Examples:

  • Mainnet: cardano-node/10.7.0
  • Testnet: amaru/1.1.0+peras
  • Privacy mode: nil

Links

Authors

Copy link
Copy Markdown
Collaborator

@rphair rphair left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @disassembler @Crypto2099 - looks quite well written; marking for Triage at next CIP meeting (https://hackmd.io/@cip-editors/130).

@rphair rphair added Category: Ledger Proposals belonging to the 'Ledger' category. State: Triage Applied to new PR afer editor cleanup on GitHub, pending CIP meeting introduction. labels Mar 7, 2026
@Crypto2099
Copy link
Copy Markdown
Collaborator

Thanks for the grammar check-up @rphair, all looked good and have been accepted/committed by me.

@gufmar
Copy link
Copy Markdown
Contributor

gufmar commented Mar 13, 2026

It’s been a week, and I was a bit surprised to see this CIP worded this way. Since the incident in November, when it became clear that better situational awareness is important and necessary, I’ve gathered various ideas and asked subject matter experts for their feedback. Even though the solution here seems relatively simple, there are a few more details that I—and some of the other people I consulted—believe need to be taken into account. Some of these are absolutely critical to safety.

I therefore request that we not proceed with this CIP in its proposed form just yet, and that we put it on hold until a proper CPS has been drafted.

In addition, I propose that we discuss this topic with various node experts from different perspectives at the next Node Diversity Workshop (expected in early May). The results should then yield a solid and broadly supported CPS and, ideally, a subsequent CIP in which a user-agent string in some form could indeed make sense.

@rphair
Copy link
Copy Markdown
Collaborator

rphair commented Mar 13, 2026

@gufmar requesting a delay sounds reasonable & we'll discuss in CIP meeting Triage on Tuesday whether this would be better in Draft status in the meantime (given also any @disassembler / @Crypto2099 responses to #1157 (comment)). In any case I think @Ryun1 @perturbing would also be reluctant to give this a number (with candidate status) under the conditions you describe.

@Crypto2099
Copy link
Copy Markdown
Collaborator

@gufmar requesting a delay sounds reasonable & we'll discuss in CIP meeting Triage on Tuesday whether this would be better in Draft status in the meantime (given also any @disassembler / @Crypto2099 responses to #1157 (comment)). In any case I think @Ryun1 @perturbing would also be reluctant to give this a number (with candidate status) under the conditions you describe.

I'm not comfortable with putting our proposed CIP on pause just because of vague allusions to some mysterious "critical to safety" things that need to be taken into account. I would much rather hear either:

  1. What the specifics of those concerns are so we can adapt the CIP accordingly or close it as unviable
  2. Hear from actual node implementers about why this is/is not a viable solution (@lehins @Quantumplation @wolf31o2)
  3. Hear an explanation of why this discussion must be held at a "Node Diversity Workshop" rather than in a public forum (here)
  4. Hear of an explanation of why a "CPS" is needed (pedantic bureaucracy?) to solve something as simple as providing a user-agent string to help identify on-chain client diversity

@gufmar
Copy link
Copy Markdown
Contributor

gufmar commented Mar 13, 2026

The discussion at the node diversity workshop makes sense because multiple node teams can efficiently discuss potential , challenging and impossible variants. That's why node diversity workshops exists.

One such vague reason is: without a proper problem statement a nicely and simple sounding idea may sounds viable for a certain purpose. But in this specific CIP the collected information is baked into blocks. Now imagine people sitting in a war room of an already halted chain. Your medium is useless then because there are no more blocks with fresh updates. And there is more which I would prefer to discuss in a professional environment with different options potentially extending and backing up each other.

I'm also happy to retire my comment here and let you go ahead with the simple thing. And then bring up my idea separately. I had shared with both of you my ideas weeks ahead and you still did just come up with your simple idea here out of nothing. So I assume you properly want it the way you formulated it. May for a specific use case ahead?

@gufmar
Copy link
Copy Markdown
Contributor

gufmar commented Mar 14, 2026

Today I’d like to add another reason why I believe that including the user-agent as a string in the Block header isn’t really the best idea to solve the problem mentioned (node version deployment situation awareness)

Let’s consider three possible ways this user agent string could be used.

  1. The ideal case: an honest SPO who has the node bake the correct (hard-coded in the released code) user-agent string into the block header. That would amount to approximately 60–80 MB of additional data per year. Fine.

  2. What if an SPO writes fake version information, inappropriate, political, or illegal content into the blocks? The other stake pools must be able to validate these blocks and rely on them within a very short time (a few seconds) while the system is running. Ledgers and consensus are capable of validating the validity of block contents based on UTXOs and the specifications. But there is nothing they could use to assess and validate an user string. The problem with potentially questionable message content is not new, because we have metadata. However, metadata always comes only as part of a valid UTXO transaction. Other SPOs would not really be in a position to ensure that their own systems do not contribute to the dissemination of false or inappropriate data in the original sense of this new user-agent field.

  3. Anyone who is still willing to turn a blind eye to 2) should open both eyes now, and not later claim they couldn’t have foreseen this. This 64-byte user-agent field can be used by stake pools (block producers) for any content. Similar to BTC op_return or ordinals. Whether this will always be limited to its intended purpose or used for completely different things... remains uncertain. In the header, it would in any case fall outside any existing specification and validation logic.

In practice, according to this CIP draft, SPOs could write data into the block headers and be paid for this entirely off-chain and outside of any Ouroboros incentive game theory. Is that the intention?

Is it acceptable that—due to the lack of real-time verifiability—potentially falsified or misused messages could be immutably written into the blockchain forever?

One possible solution is to limit the user agent to exactly two bytes. Then, the various nodes could hard-code the first byte reserved for them, along with the second digit, into their releases.

For the first byte, h could be reserved for the Haskell node and a for the Amaru node. d for Dingo, etc.
Each node team manages the second digit on its own, simply ensuring that every significant code release receives its own incremented signature... 0..1..2.. ..a..b.. and after 256 releases, they simply start over from the beginning, because it can be assumed that, in combination with the slot time and era compatibility, there is absolutely no doubt as to which code release is meant.

With such a solution, the possibility of abuse would be greatly reduced compared to a 64-byte text field. The additional fixed storage space per year, which is fairly predictable, amounts to only +3 megabytes then.

@disassembler
Copy link
Copy Markdown
Contributor Author

@gufmar - Thank you for the thoughtful feedback across both comments and for
taking the time to gather input from subject matter experts. I appreciate the
specific concerns you've raised about monitoring during chain halts and the
detailed technical analysis of the abuse potential in the user-agent field.

I want to acknowledge that you shared ideas with us weeks ago, and I
apologize if it seems like we didn't incorporate that feedback. Our intent
wasn't to dismiss those discussions, but rather to propose what we saw as a
practical starting point that could evolve through community review - which
is exactly what's happening now.

Addressing the chain-halt concern:

Regarding block-baked data during incidents: you're right that if the chain
halts, we can't get fresh block data. However, I'd argue this is
complementary to - not a replacement for - out-of-band monitoring. The
user-agent data helps with historical analysis, upgrade tracking, and
normal-operation diversity metrics. For live incident response, we'd still
rely on peer-to-peer network monitoring, node telemetry, and other real-time
channels.

Addressing the validation and abuse concerns:

Your analysis of the 64-byte field's abuse potential raises legitimate
technical issues around validation, arbitrary content insertion, and
off-chain incentives. The comparison to Bitcoin ordinals/OP_RETURN is apt -
without validation logic, SPOs could write political content, illegal data,
or be paid off-chain to insert arbitrary messages that other nodes must
propagate and store forever.

Your 2-byte proposal is clever and does solve the core use case (node
diversity metrics and upgrade tracking) while dramatically reducing abuse
vectors. Here's my analysis of the trade-offs:

What the 2-byte approach gains:

  • Eliminates arbitrary data insertion and political/illegal content risks
  • Reduces storage from ~60-80 MB to ~3 MB annually
  • Removes off-chain incentive concerns
  • Still provides implementation diversity visibility
  • Makes validation simpler (finite set of valid values)

What the 2-byte approach loses:

  • Human readability (comparing to "cardano-node/9.2.1")
  • Semantic versioning information (can't distinguish patch vs minor vs major)
  • Flexibility for new implementations (requires coordination to assign first
    byte)
  • Detailed build/platform information that might be useful for debugging
    incidents
  • After 256 releases, version cycling creates ambiguity even with slot/era
    context

Alternative approaches worth considering:

  1. Fixed-length enumerated field (4-8 bytes):
  • 2 bytes: implementation ID (allows 65k implementations, room for growth)
  • 2 bytes: major.minor version
  • Optional 4 bytes: patch/build info
  • Still limits abuse to finite enumeration space
  • ~6-12 MB annually
  1. Validated string approach:
  • Consensus rules reject blocks with user-agent strings that don't match a
    simple regex pattern (e.g., ^[a-zA-Z0-9-./]+$)
  • Max length 32 bytes instead of 64
  • Prevents illegal/political content while allowing version strings
  • Doesn't prevent fake versions, but fake versions are detectable as
    outliers in analytics
  • ~30-40 MB annually
  1. Enhanced 2-byte approach:
  • 1 byte: implementation
  • 3 bytes: semantic version (major.minor.patch, each 0-255)
  • ~6 MB annually
  • Preserves version semantics while limiting abuse

Critical timing constraint:

I understand there may be additional considerations - potentially including
security implications - that are more appropriate to discuss in a
professional setting rather than a public forum, and I respect that. However,
here's where timing becomes critical:

Network protocol upgrades for monitoring (P2P telemetry, out-of-band metrics,
etc.) can be deployed at any time without a hard fork. However, modifying
the block header requires not just any hard fork, but an intra-era hard fork

  • which is expensive, time-consuming, and happens on a very infrequent
    cadence. If we miss the Dijkstra window for this header field addition (in
    whatever form), we risk operating without on-chain node diversity visibility
    for potentially another year or more. Given that you've correctly identified
    monitoring as "critical to assess both upgrade readiness and node diversity,"
    delaying this particular capability seems counterproductive to ecosystem
    safety.

Path forward:

I'd prefer we proceed with the planned Triage discussion on Tuesday rather
than moving to Draft status. The CIP editors can evaluate:

  • Whether your concerns warrant a CPS-first approach or whether this proposal
    can move forward with modifications
  • The trade-offs between different approaches (64-byte text vs 2-byte
    enumeration vs alternatives)
  • Abuse risk vs operational utility
  • Storage impact vs information value
  • Whether consensus-level validation is sufficient or enumeration is
    necessary

I completely support discussing broader monitoring strategy at the Node
Diversity Workshop in May. In fact, a comprehensive approach could explore
multiple complementary mechanisms:

  • This CIP: On-chain identification via block headers (requires intra-era
    hard fork)
  • Network-layer telemetry with appropriate security measures (can be deployed
    without hard fork)
  • Other real-time monitoring mechanisms (can be deployed without hard fork)

The workshop can inform those alternative approaches while this CIP addresses
the specific opportunity we have during the Dijkstra planning window.

I'm genuinely open to any of these approaches - including your 2-byte
proposal - if they address your security and abuse concerns while providing
the visibility we need for ecosystem health. The goal we share is too
important to let perfect be the enemy of good, but also too important to rush
without addressing legitimate risks.

What's your assessment of the alternatives? And would you be comfortable with
the editors evaluating these options on Tuesday?

@rphair
Copy link
Copy Markdown
Collaborator

rphair commented Mar 14, 2026

@disassembler #1157 (comment): I'd prefer we proceed with the planned Triage discussion on Tuesday rather than moving to Draft status. The CIP editors can evaluate:

  • Whether your concerns warrant a CPS-first approach or whether this proposal
    can move forward with modifications

It would also be my preference to keep this proposal moving along in full review status: considering the most important part of the review is already happening now. Ideally some preliminary feedback (on an agreeable basic syntax & polling other node development teams) would have happened when this CIP was being drafted: but since we've gotten this level of visibility & discussion now I wouldn't want to interrupt it.

In any case we've made modifications to CIPs during their active review & editing cycle just as significant as the radical syntax changes proposed above.

  • The trade-offs between different approaches (64-byte text vs 2-byte enumeration vs alternatives)
  • Abuse risk vs operational utility
  • Storage impact vs information value

Personally I think semantic versioning could be achieved in 3 bytes and still be human readable (A = 10, B = 11, etc.). On the other end of the spectrum I am certain that a fully user-writable string would guarantee an apocalypse of forbidden data being written into block headers.

So generally the editors would just be adding their own common sense & experience into the already-understood problems, but mainly monitoring the discussion to see what solution the node architects, tooling experts, and disaster recovery specialists are converging upon.

  • Whether consensus-level validation is sufficient or enumeration is necessary

As I see it, questions like this are the only point at which a CPS would be considered useful (and likely just a bureaucratic hurdle otherwise). When @gufmar's suggestion of a CPS came up, the first thing I thought was, "Is there a better place for this information than the block header?"

So again the editors would be looking for a diversity of approaches to the problem solved here in the block header... and might recommend a CPS if any viable alternatives come up in review (e.g. further support for Network-based approaches mentioned in previous comments). cc @Ryun1 @perturbing

@gufmar
Copy link
Copy Markdown
Contributor

gufmar commented Mar 15, 2026

I will try to add more points over the course of the coming week, now that we have indeed begun discussing the proposed solution along with any potential supplementary or alternative solutions.

I am currently still in the interview phase with several larger stakepools. Some of these have very clear and strict operational rules, such as not publicly disclosing the current software versions of their infrastructure for their own protection. For the solutions we are aiming for (CIP), we should build on a problem statement that highlights the challenge of enabling the most comprehensive participation possible. There are ideas for this.

I’d like to elaborate further on the following points, which I’ll just mention briefly here:

Version information from block production is useful in this regard because it already presents the versions in a stake-weighted manner. However, it does not provide information about the network topology—specifically, the relays that are publicly accessible remotely between all producers. It wasn’t the first time—just this past February—that a critical security patch was distributed that affected precisely this part of the network. If we’re addressing the topic of code-release situation awareness, then in my opinion we should definitely take the network aspect into account as well.

There are people who have even more ideas for this awareness monitoring, specifically regarding the challenges of node diversity.

I also know that there are people who, while very interested in monitoring data themselves, would prefer that no one else know about it.

When I work toward discussing all of this at the Node Diversity Workshop and compiling the suggestions, reservations, and compromises so that they can then be brought to CPS and CIP, this has absolutely nothing to do with any covert operations, but rather with finding solutions that involve not only SPOs but also node developers at an early stage—and, above all, win them over. Some points are actually significantly more complicated—but also more important—than I had anticipated in early December when I first tackled the topic.

I ask that we allow sufficient time for this workstream, though we are welcome to start by requesting the attention and resources needed for a hard fork integration.

@disassembler
Copy link
Copy Markdown
Contributor Author

Version information from block production is useful in this regard because it already presents the versions in a stake-weighted manner. However, it does not provide information about the network topology—specifically, the relays that are publicly accessible remotely between all producers. It wasn’t the first time—just this past February—that a critical security patch was distributed that affected precisely this part of the network. If we’re addressing the topic of code-release situation awareness, then in my opinion we should definitely take the network aspect into account as well.

This is precisely why it should be optional, which is better than the status-quo where a node version can be identified by the baked in protocol version we've used to assess upgrades in the past.

When I work toward discussing all of this at the Node Diversity Workshop and compiling the suggestions, reservations, and compromises so that they can then be brought to CPS and CIP, this has absolutely nothing to do with any covert operations, but rather with finding solutions that involve not only SPOs but also node developers at an early stage—and, above all, win them over. Some points are actually significantly more complicated—but also more important—than I had anticipated in early December when I first tackled the topic.

@Crypto2099 and I brought this up as a problem at the inaugural Paris node diversity workshop and almost everyone was in agreement not having a standard that supported alternative nodes in the block header was a problem. This isn't a problem we invented out of a vacuum.

I ask that we allow sufficient time for this workstream, though we are welcome to start by requesting the attention and resources needed for a hard fork integration.
Sufficient time in your timeline with the future node diversity workshop 2 months out essentially means sticking with the status quo for 2-3 more years. I'm concerned with that, and so is @Crypto2099 that will hurt node diversity adoption or worse, have people abuse the current PVMajor/Minor fields to distinguish their node from others in a non-standard way that no one can agree to.

Like I said previously, I'm not against building a N2N query that helps monitoring software get more information. I'm even not against having that encrypted (although I'm not sure the general community would agree with only a small set of long-term actors having access to that data).

What I am against is not finding a solution for the problem of identifying block production between nodes with potentially 4 alternative nodes reaching block production in a testnet this year because we can't make a decision to get this into Dijkstra waiting on physical meetups, bureaucracy, politics, etc...

Furthermore, I really think the "mickey mouse" copyright violation problem being introduced in blocks is over-blown. The user agent is the same size the metadata text fields were limited to for that prevention in the transaction metadata. If the lawyers felt that size was small enough to not be a problem, I don't see why this user-agent string in headers would be a problem. I'm much more concerned with any potential performance problems from shipping around larger headers than I am the copyrighted information being included in those headers.

@gufmar
Copy link
Copy Markdown
Contributor

gufmar commented Mar 16, 2026

Indeed there are a bunch of concerns raised, not only the ones I was being told, why someone probably want any insights into node landscapes prevented.

The difference between the existing metadata and a potential new header string is, the second would be completely unrelated to any utxo, fees, relations, validation. In order to prevent reasons against doing this at all, my suggestion is to limit it to minimal bytes.

The encryption part is what I expect next will be marketed a.. f... by those who don't want any such insights shared. The reason why I would like discuss individual the SPO-decided encryption of what they expose is because any such information (in blocks or n2n) could be used for malicious players to design and time their attacks, even before the monitored data will become useful in war rooms and recovery plan executions.

My idea (! which I would have preferred discuss it with affected node teams first, instead of throwing it on them via random CIP) is to have this data encrypted for one or multiple recipients. And the first one is always the node team himself. But this would mean the node team then has to handle public/private keys, and should then also run a little infra to actually capture what SPOs offer them.
Any other monitoring entities could collect another subset of exposed data, based on what the SPOs agree and opt in in their configs.

Now those who would like to prevent all of this, please read carefully here and prepare with new reasons...

Hint: encryption computation and other such stuff it's not. Prototype demos flying in...

It's still unclear to me if we want to bring all of the problems around this "awareness" topic into a CPS first, and then decide if we go for individual CIPs, the one in this block header user agent way, with the HF complexity, and the other side mich easier to implement and deploy, but with a whole bunch of more use cases, data and processes involved. Or of we can see the benefits of baking all of it onto a common CIP, covering and ideally combining header and network informations.

@disassembler
Copy link
Copy Markdown
Contributor Author

I think we should keep the design of the N2N metrics proposal out of this CIP and keep the focus on what's proposed here. I'll work on changing the string to a smaller footprint before next CIP editors meeting. @rphair would you like me to attend to present it?

@rphair
Copy link
Copy Markdown
Collaborator

rphair commented Mar 16, 2026

yes @disassembler I think that would be a great help to the emergent discussion (@gufmar you would be equally welcome). For confirmation the time & agenda are at this link: https://hackmd.io/@cip-editors/130

@disassembler
Copy link
Copy Markdown
Contributor Author

I'll try to join 30 minutes in, It's during the release office hours meeting for the cardano-node 10.7 release, but hopefully we can wrap up in 30 minutes and I can come to the meeting.

@Crypto2099
Copy link
Copy Markdown
Collaborator

Given that so far I've only heard a few vague "Chicken Little, the Sky is Falling" threats or danger of the proposed method, which I believe to be over-stated given the relatively strict ABNF grammar that we've set (and we could easily require that this be checked as part of block validity although I think that's overkill)...

I wanted to go on record as stating that there is precedent for a human-readable "agent string" field in block headers in the form of the Graffiti field in the block headers of Ethereum blocks.

In Ethereum the Graffiti field is any 32 bytes and, as expected by the name, people do of course utilize it for self-promotion and other "non-academically-prescribed" purposes. However, the entire premise of blockchain is that he majority of control lies with honest actors who use the tools correctly and fairly. Can we really stop someone from potentially abusing this for personal advertisement (not sure who you're advertising to in the header of a block)? No. Can we stop someone from putting "illegal content" in the header of the block? No, not anymore than we can stop it in the metadata of transactions. I would argue that there is significantly higher cost to embed illegal data in the header of a block given that you have to both operate a validating node AND have enough stake to produce a block in order for that block to ever have a chance of insertion within the chain.

References:

@Crypto2099
Copy link
Copy Markdown
Collaborator

Furthermore, @gufmar suggests that there is some "danger" that dishonest actors could provide bad data through some customized build of their software to inject misleading or malicious information into the proposed field, this is equally true of his proposed N2N/N2C changes and/or his "Trust me to not be evil and send me all your encrypted data bro" solution as well. If we presume dishonesty then none of our monitoring metrics will be accurate and we may as well abandon all hope.

@disassembler
Copy link
Copy Markdown
Contributor Author

I'll agree with @Crypto2099. He showed me the precedent of a graffiti field yesterday, and I agree, if other chains are doing it, there's really no harm to us introducing this field as well. Again, I don't think a large number of SPOs will abuse it, even if one or two do.

@rphair rphair changed the title CIP-???? | Block Producer Identification and Protocol Version Signaling CIP-0180? | Block Producer Identification and Protocol Version Signaling Mar 18, 2026
Copy link
Copy Markdown
Collaborator

@rphair rphair left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@disassembler in the commits above it looks like you've already incorporated the consensus of feedback from the CIP meeting today — thanks also to you & @Crypto2099 for presenting, and for all the participation from reviewers from different disciplines.

Editors & attendees agreed a CPS would not be required to progress this CIP:

  • we don't need a more general problem statement to begin iterating solutions to such problems already witnessed in practice: and instead can adjust the solution according to a scope perhaps better defined over the course of the review process;
  • a CPS would be more useful if & when other CIPs start to talk about uses for such a writable field, but it's unreasonable to require a CPS now just because of the breadth of possibilities about how such syntax proposals & methods might interact.

The expressed reservations about putting this into in the block header itself (as @colll78 mentioned, likely causing problems with sidechains also using those headers) look like they've been addressed by recent commits moving it into the block body (offered as a solution during this meeting).

@gufmar the interest in shared data for network analytics & disaster recovery also sounded very promising and I feel sure the community would look forward to any CIP or CPS about ideas for sharing this data in any medium that's been suggested so far: the network itself, Tx or node/pool metadata, third party apps & services: as well as the new ID string itself.

Especially with today's updates, this appears to offer a new baseline for review now that editors have already agreed to declare this a candidate & assign a CIP number: @disassembler @Crypto2099 please rename the directory to CIP-0180 and update the pathname to your readable document in the initial posting. 🎉

Copy link
Copy Markdown
Collaborator

@rphair rphair left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p.s. since the Protocol Version Signaling has been defined as the purpose of Block Producer Identification, I'd propose that this shorter title should be applied to the PR as well.

... OR (@disassembler @Crypto2099) — perhaps anticipating other uses of such an "Identification" field, the use for "Signaling" defined here could become essential once other related CIPs or a CPS comes along... in that case you/we might want to change this to the longer title...

@rphair rphair added State: Confirmed Candiate with CIP number (new PR) or update under review. and removed State: Triage Applied to new PR afer editor cleanup on GitHub, pending CIP meeting introduction. labels Mar 18, 2026
Copy link
Copy Markdown
Contributor

@ch1bo ch1bo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Putting it into the body resolves most of my concerns around keeping block headers small to ensure rapid dissemination required for blockchain safety (in the ouroboros praos and related protocols).

There are other CIPs that look into changing the header and body and aim for Dijkstra (Block body segregation, Leios, Peras and the merkle tree in the header come to mind .. there might be more). So it seems to be a good time to do this.


1. **Block Producer Identification**: Adds a new optional 6th element to the
block body - a free-form text field (max 32 bytes) similar to HTTP user-agent
strings (RFC 9110, Section 10.1.5)<sup>1</sup> that allows block producers to
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Markdown supports footnotes1

Footnotes

  1. they are quite cool

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Markdown to generate the above comment, precisely:

Markdown supports footnotes[^1]


[^1]: they are quite cool

As a Ledger category CIP per CIP-0084<sup>3</sup>, the specification below is
intended to be sufficiently detailed for inclusion in a formal ledger
specification. The complete CDDL specification for these changes will be added
to Cardano Blueprint<sup>2</sup> as the authoritative reference for all
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩵

, transaction_witness_sets : [* transaction_witness_set]
, auxiliary_data_set : {* transaction_index => auxiliary_data}
, invalid_transactions : [* transaction_index]
, producer_agent : tstr .size (0..32) / nil ; NEW - optional
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that this is put at the end of the block body, so cardano nodes can choose to to stop loading / decoding after the non-optional parts (and not need to seek over this variable size part)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a specific mention that the producer agent should always be the final element of the block body for this particular reason? i.e.

The producer_agent as well as any additional, future fields that provide simple information only should always be the last elements of the block body to allow for optimized processing

???

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that this is put at the end of the block body, so cardano nodes can choose to to stop loading / decoding after the non-optional parts (and not need to seek over this variable size part)

cardano-node can't choose to do that, because:

  • cardano-node need to load all of the block anyways for the purpose of block body hash calculation
  • cardano-node needs to decode the whole block to ensure structural integrity of the block.

So, from Ledger and block validation perspective it doesn't matter where is it: in the beginning, in the end or somewhere in the middle.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, if the hash includes it. But excluding it is probably not worth the hassle. This is resolved.

Add a new optional text field to the block body for node identification:

```cddl
producer_agent = tstr .size (0..32) / nil
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the sum with nil = #7.22 and not just tstr .size (0..32) with opt-out being just the empty text string.

Also, do we allow indefinite length text strings here or only definite length text strings? (CBOR and CDDL do allow it interchangedly, but maybe we want to constrain it?)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that both are 1-byte I think it's easier and cleaner just to leave it as a potentially empty text string here. Thoughts @disassembler

Copy link
Copy Markdown
Contributor

@lehins lehins Mar 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There can be semantic difference between "empty string" and "string not provided".

Also they are not both 1-byte

With definitely length encoding you have: tag + 0 length (2 bytes), with indefinite you have start tag + end tag (2 bytes). While with nil it is indeed only 1 byte

So, what I would recommend is doing this:

Suggested change
producer_agent = tstr .size (0..32) / nil
producer_agent = tstr .size (1..32) / nil

Which means, if the string is provided, it must be non-empty, otherwise it must be nil

We take the same approach in most of the fields in the tarnsaction

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lehins My comment was more about to keep it simple so we have the littlest code about this in the cardano-node. It's not about byte size, because if it were, we should ask for 31 bytes .. or even less (but that is already discussed in the cip).

Hence, what would you say is the dead simplest, smallest implementation and hardest to get wrong encoder for this?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldnt we do this is a structured format like the rest already is, with a key index number and than a content?

like key index 0, and than the content is the producer_agent bytearray. key index 1 something else in the future, etc and rename it to a more general name for this section?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be in favor of making this an array/object to start with so its relatively easy to extend in the future, the problem is that CBOR (afaik) does not limit "extra fields allowed" the same way that JSON schema does.

There is really no need to do any of this.

All of those things can be done of chain. We could even use this field as an identifier and the full data about this is stored somewhere off chain.

It can be even be a git commit of the actual software indicating the exact piece of software that is minting this block. Possibilities are endless with 32bytes.

What we don't want is a precise definition of its meaning on chain! Because any change to it would require a hard fork!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would require a hard fork!

Oh yeah, not even just a hard fork, but a whole new era. We can't change serialziation for intra-era hard forks

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nevermind... but please excuse my 2nd thoughts about implementations. i mentioned that back in the days when native asset were introduced. what was missing, a single byte that sets the decimals. caused huge issue afterwards.
when it came to the drep governance stuff, i called to reflect on that and that we maybe need some additional bytes. was rejected, the result was that we had to upgrade to cip129 afterwards. and the list goes on.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have a list of bad ideas that you ever suggested? 😅

Please, don't get me wrong. I always do appreciate when people suggest ideas! But, you gotta forgive me when I have to push back on some of them, cause not all ideas should see the future. It is always better to select few good ones from many ideas, than not have any ideas at all to choose from! So, please keep them coming and don't let me discourage you.

Trust me, if I was around when MultiAsssets were being introduced I would have myself pushed really hard for adding a decimal point. I even have a Haskell library called safe-decimal 😂

Copy link
Copy Markdown
Contributor

@ch1bo ch1bo Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@disassembler As OP of this thread, my comment was "can we keep this as simple as possible please".

I would have accepted @lehins opinion in #1157 (comment) and resolved this.

Then, we went into the opposite direction with the informational_data_set suggestion of making a tstr .size (1..32) / nil into [ tstr .size (1..32) / nil ] / nil (which can be more than 32 bytes BTW). After a discussing of that suggestion, it seemed to have been withdrawn / resolved.

However, the CIP was now changed to use informational_data_set???

@gitmachtl
Copy link
Copy Markdown
Contributor

gitmachtl commented Mar 18, 2026

so, moving the additional info data to the block body and reducing protocol version in the header from [major,minor] to just [major]... why don't we also remove the PV completely from the header and add it to the additional info data?

if have understood the changes in the intention of the PV correct, that should signal the maximum PV a node can support. for that, the minor is not important anymore? the PV major is not used for consensus?

so PV info is only informational, why not also move it to the additional field together with the user-agent data to the producer_agent entry? would reduce the header size even more?

@lehins
Copy link
Copy Markdown
Contributor

lehins commented Mar 18, 2026

so PV info is only informational, why not also move it to the additional field together with the user-agent data to the producer_agent entry?

It is not strictly informational. It is used to reject blocks from SPOs that were too lazy to upgrade their software

@Crypto2099
Copy link
Copy Markdown
Collaborator

so PV info is only informational, why not also move it to the additional field together with the user-agent data to the producer_agent entry?

It is not strictly informational. It is used to reject blocks from SPOs that were too lazy to upgrade their software

So, if I understand this correctly, if we are in PV = 10 currently and we see a block from a producer who has PV: 9 in the header, we can reject it quicker (pre-validation) because we know it is not in the right era/PV?

@gitmachtl
Copy link
Copy Markdown
Contributor

It is not strictly informational. It is used to reject blocks from SPOs that were too lazy to upgrade their software

ok, but removing the minor field would also make it incompatible. and we need a hardfork anyway.

@Crypto2099
Copy link
Copy Markdown
Collaborator

It is not strictly informational. It is used to reject blocks from SPOs that were too lazy to upgrade their software

ok, but removing the minor field would also make it incompatible. and we need a hardfork anyway.

AFAIK the minor version has never actually been used except for the rare case of attempting to specifically monitor the upgraded readiness of specifically the Haskell cardano-node historically. This would be resolved via the producer-agent string in the future when multiple nodes will all have different major/minor versions to indicate readiness? Or can the on-chain Minor be incremented via HF, in which case it likely needs to be left in the header.

@gitmachtl
Copy link
Copy Markdown
Contributor

gitmachtl commented Mar 18, 2026

because we know it is not in the right era/PV?

but we can also do hardforks from PV 10.0 to PV 10.1 for example. thats why i am a bit confused that the minor is not needed anymore.

@gitmachtl
Copy link
Copy Markdown
Contributor

gitmachtl commented Mar 18, 2026

Or can the on-chain Minor be incremented via HF

yes it can, and there are rules for it that the minor can only be increased by one. (unless it was changed?)
and if you are increasing the major, the minor must be zero.

EDIT: hah, @lehins did the specs change for dijkstra?

hard_fork_initiation_action = (1, gov_action_id/ nil, protocol_version)

protocol_version = [major_protocol_version, uint .size 4]

There is only a major_protocol_version in the CDDL, but

the HardForkInitiation action contains the choosen [major.minor] version to fork to. Example:

cbor-diag <<< "841b000000174876e800581de0c13582aec9a44fcc6d984be003c5058c660e1d2ff1370fd8b49ba73f830182582052f8f9190c858f918fa65c1b9370df11477609ae95ff72da74226613632f4c9a00820b0282781f68747470733a2f2f6d792d69702e61742f746573742f746573742e6a736f6e5820a442c294a385e0e52cee6441e8c3743ee9953b24d93bfb406762cb1b94aa84c2"
[
    100000000000_3,
    h'e0c13582aec9a44fcc6d984be003c5058c660e1d2ff1370fd8b49ba73f',
    [
        1,
        [
            h'52f8f9190c858f918fa65c1b9370df11477609ae95ff72da74226613632f4c9a',
            0,
        ],
        [11, 2],
    ],
    [
        "https://example.com",
        h'a442c294a385e0e52cee6441e8c3743ee9953b24d93bfb406762cb1b94aa84c2',
    ],
]

This is for a hardfork to 11.2

@lehins
Copy link
Copy Markdown
Contributor

lehins commented Mar 18, 2026

So, if I understand this correctly, if we are in PV = 10 currently and we see a block from a producer who has PV: 9 in the header, we can reject it quicker (pre-validation) because we know it is not in the right era/PV?

Correct. That is how it has always worked.

ok, but removing the minor field would also make it incompatible. and we need a hardfork anyway.

Correct. And by adding this new 32 byte long field we no longer need to abuse that minor version anymore, so it becomes totally useless.

AFAIK the minor version has never actually been used except for the rare case of attempting to specifically monitor the upgraded readiness of specifically the Haskell cardano-node historically.

That is exactly right. With this CIP that minor version in the header has no meaning or use whatsoever

Or can the on-chain Minor be incremented via HF, in which case it likely needs to be left in the header.

It can be incremented through the onchain governance, but because it is a minor version, there cannot be any changes to semantics that would invalidate the chain. i.e. node running x.0 version must also be compatible with x.1 protocol version

@disassembler disassembler force-pushed the sl-ad/block-producer-id branch from a5706bb to 149a167 Compare March 20, 2026 03:41
Allow producers to identify their node implementation and version, similar to HTTP user-agent strings.

- Add informational_dataset structure as 6th block element
- provide examples for different node implementations
- Supports testnet build metadata examples (+leios, +peras, +mithril)
- Includes CBOR encoding examples
- Match Ethereum graffiti precedent (32 bytes)

Co-authored-by: Adam Dean <adam@crypto2099.io>
Co-authored-by: Robert Phair <rphair@cosd.com>
Co-authored-by: Sebastian Nagel <ch1bo@users.noreply.github.com>
@disassembler disassembler changed the title CIP-0180? | Block Producer Identification and Protocol Version Signaling CIP-0180? | Block Producer Identification Mar 20, 2026
@disassembler disassembler force-pushed the sl-ad/block-producer-id branch from 149a167 to e3408c0 Compare March 20, 2026 03:49
@ch1bo
Copy link
Copy Markdown
Contributor

ch1bo commented Mar 20, 2026

@disassembler I learned that we don't like force pushes on PRs to CIPs from @rphair. It really makes it hard to point to changes.

@rphair
Copy link
Copy Markdown
Collaborator

rphair commented Mar 20, 2026

yes @disassembler what @ch1bo says is true... especially important for a draft like this with so much contended detail, each with its own thread of related discussion.

Now that 1 or 2 major revisions have incorporated community feedback, you could treat the current state like a baseline: committing suggested changes here from the GitHub UI (in addition to your own update commits pushed here) & pulling the UI commits back to your working fork. 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Category: Ledger Proposals belonging to the 'Ledger' category. State: Confirmed Candiate with CIP number (new PR) or update under review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants