Skip to content

Commit eea7ac3

Browse files
committed
fix: fail withdrawals on pv10/pv11 w/o drep
Signed-off-by: Chris Gianelloni <wolf31o2@blinklabs.io>
1 parent 58c5d1c commit eea7ac3

20 files changed

Lines changed: 319 additions & 31 deletions

File tree

ARCHITECTURE.md

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ Gouroboros is a Go implementation of the Cardano blockchain protocol, providing
4040
┌────────┴─────────────────────────────────┐
4141
│ Era-Specific Implementations │
4242
│ Byron → Shelley → Allegra → Mary → │
43-
│ Alonzo → Babbage → Conway → Leios
43+
│ Alonzo → Babbage → Conway → Dijkstra
4444
└───────────────────────────────────────────┘
4545
4646
┌────────┴──────────────┬──────────────┬────────────┐
@@ -139,7 +139,9 @@ type TransactionBody interface {
139139

140140
### Era Hierarchy
141141

142-
Each era builds on the previous, delegating unchanged validation rules:
142+
Post-Byron eras build on their predecessors and may delegate individual
143+
validation rules when their behavior is unchanged. Delegation is not
144+
universal; era-specific rule bodies must be inspected before assuming it.
143145

144146
```
145147
Byron (genesis)
@@ -149,12 +151,18 @@ Byron (genesis)
149151
└─ Alonzo (Plutus scripts)
150152
└─ Babbage (reference scripts)
151153
└─ Conway (governance)
152-
└─ Leios (experimental)
154+
└─ Dijkstra (PV12)
153155
```
154156

157+
Leios is not a ledger era. It is a higher-throughput overlay protocol
158+
introduced with Dijkstra; its shared ledger types live in
159+
`ledger/common/leios*.go`, and its mini-protocols live under
160+
`protocol/leios{fetch,notify,votes}/`.
161+
155162
### Validation Pattern
156163

157-
Each era defines validation rules that delegate to earlier eras for unchanged logic:
164+
Each era defines its validation rules. A rule can delegate to an earlier era
165+
when its behavior is unchanged:
158166

159167
```go
160168
// shelley/rules.go - defines base rules
@@ -181,8 +189,38 @@ func UtxoValidateTimeToLive(tx, slot, ls, pp) error {
181189
| Mary | Multi-asset support (native tokens) |
182190
| Alonzo | Plutus smart contracts, redeemers, datums |
183191
| Babbage | Reference scripts, inline datums |
184-
| Conway | On-chain governance, DReps, proposals |
185-
| Leios | Experimental (input blocks, endorser blocks) |
192+
| Conway | Governance; PV10/PV11 DRep-gated reward withdrawals |
193+
| Dijkstra | PV12; CIP-181 removes the reward-withdrawal DRep gate |
194+
195+
### Conway Reward Withdrawal Gate
196+
197+
`conway.UtxoValidateWithdrawals` has an era-specific implementation. It skips
198+
withdrawal validation for phase-2-invalid transactions, then applies the
199+
Shelley reward-account registration check. For transactions with withdrawals,
200+
the remaining behavior is selected by the active major protocol version:
201+
202+
| Protocol version | DRep vote delegation required? |
203+
|------------------|-------------------------------|
204+
| PV9 and earlier | No |
205+
| PV10 (Plomin) and PV11 (Van Rossem) | Yes |
206+
| PV12 (Dijkstra) and later | No, per CIP-181 |
207+
208+
The active protocol version comes from
209+
`conway.ConwayProtocolParameters.ProtocolMajorVersion`; Dijkstra protocol
210+
parameters inherit that method. At PV10/PV11, ledger states must additionally
211+
implement the optional `common.DRepDelegationState` capability:
212+
213+
```go
214+
type DRepDelegationState interface {
215+
DRepDelegation(Credential) (*Drep, error)
216+
}
217+
```
218+
219+
A `nil` delegation rejects the withdrawal with
220+
`WithdrawalNotDelegatedToDRepError`. A ledger state that cannot perform the
221+
lookup returns `DRepDelegationStateUnavailableError`. The capability is kept
222+
separate from `common.LedgerState` so implementations that do not validate
223+
PV10/PV11 withdrawals do not need to provide it.
186224

187225
## Protocol Layer (protocol/)
188226

@@ -465,7 +503,8 @@ ls := ledgertest.NewLedgerStateBuilder().
465503

466504
## Design Principles
467505

468-
1. Era Delegation: Later eras delegate unchanged rules to earlier eras, minimizing duplication.
506+
1. Era Delegation: Later eras may delegate unchanged rules to earlier eras,
507+
while changed rules retain era-specific implementations.
469508

470509
2. Interface-Based Validation: Rules operate on interfaces, enabling easy mocking and cross-era compatibility.
471510

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ grep -cE "^ --- FAIL: TestRulesConformanceVectors/" /tmp/conformance.txt
4444

4545
## Rules Claude gets wrong without being told
4646

47-
1. Era delegation is not universal. Conway `UtxoValidateWithdrawals` has its own body with an intentional spec deviation (`NOTE:`). Grep the function before describing behavior.
47+
1. Era delegation is not universal — grep the era's function body before describing behavior; don't assume it forwards to the previous era. E.g. `conway.UtxoValidateWithdrawals` (`ledger/conway/rules.go`) skips phase-2-invalid txs, checks reward-account registration, requires a DRep vote delegation at PV10/PV11, and removes that requirement at PV12 per CIP-181.
4848
2. `DecodeStoreCbor` requires a custom `UnmarshalCBOR` that calls `SetCbor(cborData)`. Missing → `Cbor()` returns nil → hashing breaks.
4949
3. Hash from preserved `.Cbor()` bytes. Never re-encode and hash.
5050
4. CBOR `EncMode`/`DecMode` are globally cached via `sync.Once` in `cbor/{encode,decode}.go`. Don't construct per call.

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,20 +147,23 @@ This is not an exhaustive list of existing and planned features, but it covers t
147147
- [X] TX inputs
148148
- [X] TX outputs
149149
- [X] Parameter updates
150+
- [X] Reward withdrawals require a DRep vote delegation at PV10/PV11
150151
- [X] Dijkstra
151152
- [X] Blocks
152153
- [X] Transactions
153154
- [X] TX inputs
154155
- [X] TX outputs
155156
- [X] Parameter updates
157+
- [X] Reward withdrawals no longer require a DRep vote delegation at
158+
PV12+ ([CIP-0181](https://cips.cardano.org/cip/CIP-0181))
156159
- [X] Transaction attributes
157160
- [X] Inputs
158161
- [X] Outputs
159162
- [X] Metadata
160163
- [X] Fees
161164
- [X] TTL
162165
- [X] Certificates
163-
- [X] Staking reward withdrawls
166+
- [X] Staking reward withdrawals
164167
- [X] Protocol parameter updates
165168
- [X] Auxiliary data hash
166169
- [X] Validity interval start

examples/block-fetch/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608
44
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
55
github.com/bits-and-blooms/bitset v1.24.4 h1:95H15Og1clikBrKr/DuzMXkQzECs1M6hhoGXLwLQOZE=
66
github.com/bits-and-blooms/bitset v1.24.4/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
7-
github.com/blinklabs-io/ouroboros-mock v0.14.0 h1:tWOjItzHmdcGv1HfH23jJxumOQ0wbeRnayG4mQv5QQg=
8-
github.com/blinklabs-io/ouroboros-mock v0.14.0/go.mod h1:nvY6cwqImZekjCfuutzTjdMR4/gOkNUO9lZuOGlQGl4=
7+
github.com/blinklabs-io/ouroboros-mock v0.15.0 h1:IB35erNGObqilpOLkrmdp0fH2aKKoVLW9pis7HkGve0=
8+
github.com/blinklabs-io/ouroboros-mock v0.15.0/go.mod h1:ysGU8dMjG8ShMQco/aarR1xIRH7GPCIdhrnkM+J4IVA=
99
github.com/blinklabs-io/plutigo v0.1.17 h1:44JJf9Y4G7fminNJp4H6fBQbW8nzrevSlap9a1V0EHs=
1010
github.com/blinklabs-io/plutigo v0.1.17/go.mod h1:X+Ydplpgftjjq5Y1Oc3dRebGgdBSeAbOi1+ItJhQths=
1111
github.com/btcsuite/btcd/btcec/v2 v2.5.0 h1:KioMXOWa76b86sTZZOmbzv/ldaQCmB8KFAyn5PbB8E8=

examples/chain-sync/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608
44
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
55
github.com/bits-and-blooms/bitset v1.24.4 h1:95H15Og1clikBrKr/DuzMXkQzECs1M6hhoGXLwLQOZE=
66
github.com/bits-and-blooms/bitset v1.24.4/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
7-
github.com/blinklabs-io/ouroboros-mock v0.14.0 h1:tWOjItzHmdcGv1HfH23jJxumOQ0wbeRnayG4mQv5QQg=
8-
github.com/blinklabs-io/ouroboros-mock v0.14.0/go.mod h1:nvY6cwqImZekjCfuutzTjdMR4/gOkNUO9lZuOGlQGl4=
7+
github.com/blinklabs-io/ouroboros-mock v0.15.0 h1:IB35erNGObqilpOLkrmdp0fH2aKKoVLW9pis7HkGve0=
8+
github.com/blinklabs-io/ouroboros-mock v0.15.0/go.mod h1:ysGU8dMjG8ShMQco/aarR1xIRH7GPCIdhrnkM+J4IVA=
99
github.com/blinklabs-io/plutigo v0.1.17 h1:44JJf9Y4G7fminNJp4H6fBQbW8nzrevSlap9a1V0EHs=
1010
github.com/blinklabs-io/plutigo v0.1.17/go.mod h1:X+Ydplpgftjjq5Y1Oc3dRebGgdBSeAbOi1+ItJhQths=
1111
github.com/btcsuite/btcd/btcec/v2 v2.5.0 h1:KioMXOWa76b86sTZZOmbzv/ldaQCmB8KFAyn5PbB8E8=

examples/chain-tip/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608
44
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
55
github.com/bits-and-blooms/bitset v1.24.4 h1:95H15Og1clikBrKr/DuzMXkQzECs1M6hhoGXLwLQOZE=
66
github.com/bits-and-blooms/bitset v1.24.4/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
7-
github.com/blinklabs-io/ouroboros-mock v0.14.0 h1:tWOjItzHmdcGv1HfH23jJxumOQ0wbeRnayG4mQv5QQg=
8-
github.com/blinklabs-io/ouroboros-mock v0.14.0/go.mod h1:nvY6cwqImZekjCfuutzTjdMR4/gOkNUO9lZuOGlQGl4=
7+
github.com/blinklabs-io/ouroboros-mock v0.15.0 h1:IB35erNGObqilpOLkrmdp0fH2aKKoVLW9pis7HkGve0=
8+
github.com/blinklabs-io/ouroboros-mock v0.15.0/go.mod h1:ysGU8dMjG8ShMQco/aarR1xIRH7GPCIdhrnkM+J4IVA=
99
github.com/blinklabs-io/plutigo v0.1.17 h1:44JJf9Y4G7fminNJp4H6fBQbW8nzrevSlap9a1V0EHs=
1010
github.com/blinklabs-io/plutigo v0.1.17/go.mod h1:X+Ydplpgftjjq5Y1Oc3dRebGgdBSeAbOi1+ItJhQths=
1111
github.com/btcsuite/btcd/btcec/v2 v2.5.0 h1:KioMXOWa76b86sTZZOmbzv/ldaQCmB8KFAyn5PbB8E8=

examples/peer-sharing/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608
44
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
55
github.com/bits-and-blooms/bitset v1.24.4 h1:95H15Og1clikBrKr/DuzMXkQzECs1M6hhoGXLwLQOZE=
66
github.com/bits-and-blooms/bitset v1.24.4/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
7-
github.com/blinklabs-io/ouroboros-mock v0.14.0 h1:tWOjItzHmdcGv1HfH23jJxumOQ0wbeRnayG4mQv5QQg=
8-
github.com/blinklabs-io/ouroboros-mock v0.14.0/go.mod h1:nvY6cwqImZekjCfuutzTjdMR4/gOkNUO9lZuOGlQGl4=
7+
github.com/blinklabs-io/ouroboros-mock v0.15.0 h1:IB35erNGObqilpOLkrmdp0fH2aKKoVLW9pis7HkGve0=
8+
github.com/blinklabs-io/ouroboros-mock v0.15.0/go.mod h1:ysGU8dMjG8ShMQco/aarR1xIRH7GPCIdhrnkM+J4IVA=
99
github.com/blinklabs-io/plutigo v0.1.17 h1:44JJf9Y4G7fminNJp4H6fBQbW8nzrevSlap9a1V0EHs=
1010
github.com/blinklabs-io/plutigo v0.1.17/go.mod h1:X+Ydplpgftjjq5Y1Oc3dRebGgdBSeAbOi1+ItJhQths=
1111
github.com/btcsuite/btcd/btcec/v2 v2.5.0 h1:KioMXOWa76b86sTZZOmbzv/ldaQCmB8KFAyn5PbB8E8=

examples/ping/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608
44
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
55
github.com/bits-and-blooms/bitset v1.24.4 h1:95H15Og1clikBrKr/DuzMXkQzECs1M6hhoGXLwLQOZE=
66
github.com/bits-and-blooms/bitset v1.24.4/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
7-
github.com/blinklabs-io/ouroboros-mock v0.14.0 h1:tWOjItzHmdcGv1HfH23jJxumOQ0wbeRnayG4mQv5QQg=
8-
github.com/blinklabs-io/ouroboros-mock v0.14.0/go.mod h1:nvY6cwqImZekjCfuutzTjdMR4/gOkNUO9lZuOGlQGl4=
7+
github.com/blinklabs-io/ouroboros-mock v0.15.0 h1:IB35erNGObqilpOLkrmdp0fH2aKKoVLW9pis7HkGve0=
8+
github.com/blinklabs-io/ouroboros-mock v0.15.0/go.mod h1:ysGU8dMjG8ShMQco/aarR1xIRH7GPCIdhrnkM+J4IVA=
99
github.com/blinklabs-io/plutigo v0.1.17 h1:44JJf9Y4G7fminNJp4H6fBQbW8nzrevSlap9a1V0EHs=
1010
github.com/blinklabs-io/plutigo v0.1.17/go.mod h1:X+Ydplpgftjjq5Y1Oc3dRebGgdBSeAbOi1+ItJhQths=
1111
github.com/btcsuite/btcd/btcec/v2 v2.5.0 h1:KioMXOWa76b86sTZZOmbzv/ldaQCmB8KFAyn5PbB8E8=

examples/state-query/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608
44
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
55
github.com/bits-and-blooms/bitset v1.24.4 h1:95H15Og1clikBrKr/DuzMXkQzECs1M6hhoGXLwLQOZE=
66
github.com/bits-and-blooms/bitset v1.24.4/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
7-
github.com/blinklabs-io/ouroboros-mock v0.14.0 h1:tWOjItzHmdcGv1HfH23jJxumOQ0wbeRnayG4mQv5QQg=
8-
github.com/blinklabs-io/ouroboros-mock v0.14.0/go.mod h1:nvY6cwqImZekjCfuutzTjdMR4/gOkNUO9lZuOGlQGl4=
7+
github.com/blinklabs-io/ouroboros-mock v0.15.0 h1:IB35erNGObqilpOLkrmdp0fH2aKKoVLW9pis7HkGve0=
8+
github.com/blinklabs-io/ouroboros-mock v0.15.0/go.mod h1:ysGU8dMjG8ShMQco/aarR1xIRH7GPCIdhrnkM+J4IVA=
99
github.com/blinklabs-io/plutigo v0.1.17 h1:44JJf9Y4G7fminNJp4H6fBQbW8nzrevSlap9a1V0EHs=
1010
github.com/blinklabs-io/plutigo v0.1.17/go.mod h1:X+Ydplpgftjjq5Y1Oc3dRebGgdBSeAbOi1+ItJhQths=
1111
github.com/btcsuite/btcd/btcec/v2 v2.5.0 h1:KioMXOWa76b86sTZZOmbzv/ldaQCmB8KFAyn5PbB8E8=

examples/tx-monitor/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608
44
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
55
github.com/bits-and-blooms/bitset v1.24.4 h1:95H15Og1clikBrKr/DuzMXkQzECs1M6hhoGXLwLQOZE=
66
github.com/bits-and-blooms/bitset v1.24.4/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
7-
github.com/blinklabs-io/ouroboros-mock v0.14.0 h1:tWOjItzHmdcGv1HfH23jJxumOQ0wbeRnayG4mQv5QQg=
8-
github.com/blinklabs-io/ouroboros-mock v0.14.0/go.mod h1:nvY6cwqImZekjCfuutzTjdMR4/gOkNUO9lZuOGlQGl4=
7+
github.com/blinklabs-io/ouroboros-mock v0.15.0 h1:IB35erNGObqilpOLkrmdp0fH2aKKoVLW9pis7HkGve0=
8+
github.com/blinklabs-io/ouroboros-mock v0.15.0/go.mod h1:ysGU8dMjG8ShMQco/aarR1xIRH7GPCIdhrnkM+J4IVA=
99
github.com/blinklabs-io/plutigo v0.1.17 h1:44JJf9Y4G7fminNJp4H6fBQbW8nzrevSlap9a1V0EHs=
1010
github.com/blinklabs-io/plutigo v0.1.17/go.mod h1:X+Ydplpgftjjq5Y1Oc3dRebGgdBSeAbOi1+ItJhQths=
1111
github.com/btcsuite/btcd/btcec/v2 v2.5.0 h1:KioMXOWa76b86sTZZOmbzv/ldaQCmB8KFAyn5PbB8E8=

0 commit comments

Comments
 (0)