Skip to content

Commit 41fec8c

Browse files
authored
feat: Conway era 'Utxo' validation rules (#931)
This also moves the Babbage-era disjoint ref inputs validation to Conway. It was defined in Babbage in the Haskell code, but it only actually does anything in the Conway era Fixes #880 Signed-off-by: Aurora Gaffney <[email protected]>
1 parent 44eb8bd commit 41fec8c

File tree

7 files changed

+1906
-105
lines changed

7 files changed

+1906
-105
lines changed

ledger/babbage/errors.go

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,8 @@ package babbage
1616

1717
import (
1818
"fmt"
19-
"strings"
20-
21-
"github.com/blinklabs-io/gouroboros/ledger/common"
2219
)
2320

24-
type NonDisjointRefInputsError struct {
25-
Inputs []common.TransactionInput
26-
}
27-
28-
func (e NonDisjointRefInputsError) Error() string {
29-
tmpInputs := make([]string, 0, len(e.Inputs))
30-
for idx, tmpInput := range e.Inputs {
31-
tmpInputs[idx] = tmpInput.String()
32-
}
33-
return "non-disjoint reference inputs: " + strings.Join(tmpInputs, ", ")
34-
}
35-
3621
type TooManyCollateralInputsError struct {
3722
Provided uint
3823
Max uint

ledger/babbage/rules.go

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import (
2626
)
2727

2828
var UtxoValidationRules = []common.UtxoValidationRuleFunc{
29-
UtxoValidateDisjointRefInputs,
3029
UtxoValidateOutsideValidityIntervalUtxo,
3130
UtxoValidateInputSetEmptyUtxo,
3231
UtxoValidateFeeTooSmallUtxo,
@@ -46,24 +45,6 @@ var UtxoValidationRules = []common.UtxoValidationRuleFunc{
4645
UtxoValidateTooManyCollateralInputs,
4746
}
4847

49-
func UtxoValidateDisjointRefInputs(tx common.Transaction, slot uint64, ls common.LedgerState, pp common.ProtocolParameters) error {
50-
commonInputs := []common.TransactionInput{}
51-
for _, refInput := range tx.ReferenceInputs() {
52-
for _, input := range tx.Inputs() {
53-
if refInput.String() != input.String() {
54-
continue
55-
}
56-
commonInputs = append(commonInputs, input)
57-
}
58-
}
59-
if len(commonInputs) == 0 {
60-
return nil
61-
}
62-
return NonDisjointRefInputsError{
63-
Inputs: commonInputs,
64-
}
65-
}
66-
6748
func UtxoValidateOutsideValidityIntervalUtxo(tx common.Transaction, slot uint64, ls common.LedgerState, pp common.ProtocolParameters) error {
6849
return allegra.UtxoValidateOutsideValidityIntervalUtxo(tx, slot, ls, pp)
6950
}

ledger/babbage/rules_test.go

Lines changed: 0 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,77 +1290,6 @@ func TestUtxoValidateExUnitsTooBigUtxo(t *testing.T) {
12901290
)
12911291
}
12921292

1293-
func TestUtxoValidateDisjointRefInputs(t *testing.T) {
1294-
testInputTxId := "d228b482a1aae768e4a796380f49e021d9c21f70d3c12cb186b188dedfc0ee22"
1295-
testTx := &babbage.BabbageTransaction{
1296-
Body: babbage.BabbageTransactionBody{},
1297-
}
1298-
testLedgerState := testLedgerState{}
1299-
testSlot := uint64(0)
1300-
testProtocolParams := &babbage.BabbageProtocolParameters{}
1301-
// Non-disjoint ref inputs
1302-
t.Run(
1303-
"non-disjoint ref inputs",
1304-
func(t *testing.T) {
1305-
testTx.Body.TxInputs = shelley.NewShelleyTransactionInputSet(
1306-
[]shelley.ShelleyTransactionInput{
1307-
shelley.NewShelleyTransactionInput(testInputTxId, 0),
1308-
},
1309-
)
1310-
testTx.Body.TxReferenceInputs = []shelley.ShelleyTransactionInput{
1311-
shelley.NewShelleyTransactionInput(testInputTxId, 0),
1312-
}
1313-
err := babbage.UtxoValidateDisjointRefInputs(
1314-
testTx,
1315-
testSlot,
1316-
testLedgerState,
1317-
testProtocolParams,
1318-
)
1319-
if err == nil {
1320-
t.Errorf(
1321-
"UtxoValidateDisjointRefInputs should fail when inputs and ref inputs are duplicated",
1322-
)
1323-
return
1324-
}
1325-
testErrType := babbage.NonDisjointRefInputsError{}
1326-
assert.IsType(
1327-
t,
1328-
testErrType,
1329-
err,
1330-
"did not get expected error type: got %T, wanted %T",
1331-
err,
1332-
testErrType,
1333-
)
1334-
},
1335-
)
1336-
// Disjoint ref inputs
1337-
t.Run(
1338-
"disjoint ref inputs",
1339-
func(t *testing.T) {
1340-
testTx.Body.TxInputs = shelley.NewShelleyTransactionInputSet(
1341-
[]shelley.ShelleyTransactionInput{
1342-
shelley.NewShelleyTransactionInput(testInputTxId, 0),
1343-
},
1344-
)
1345-
testTx.Body.TxReferenceInputs = []shelley.ShelleyTransactionInput{
1346-
shelley.NewShelleyTransactionInput(testInputTxId, 1),
1347-
}
1348-
err := babbage.UtxoValidateDisjointRefInputs(
1349-
testTx,
1350-
testSlot,
1351-
testLedgerState,
1352-
testProtocolParams,
1353-
)
1354-
if err != nil {
1355-
t.Errorf(
1356-
"UtxoValidateDisjointRefInputs should succeed when inputs and ref inputs are not duplicated\n got error: %v",
1357-
err,
1358-
)
1359-
}
1360-
},
1361-
)
1362-
}
1363-
13641293
func TestUtxoValidateCollateralEqBalance(t *testing.T) {
13651294
testInputTxId := "d228b482a1aae768e4a796380f49e021d9c21f70d3c12cb186b188dedfc0ee22"
13661295
var testInputAmount uint64 = 20_000_000

ledger/conway/conway.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,15 @@ type ConwayTransactionInputSet struct {
236236
items []shelley.ShelleyTransactionInput
237237
}
238238

239+
func NewConwayTransactionInputSet(
240+
items []shelley.ShelleyTransactionInput,
241+
) ConwayTransactionInputSet {
242+
s := ConwayTransactionInputSet{
243+
items: items,
244+
}
245+
return s
246+
}
247+
239248
func (s *ConwayTransactionInputSet) UnmarshalCBOR(data []byte) error {
240249
// This overrides the Shelley behavior that explicitly disallowed tag-wrapped sets
241250
var tmpData []shelley.ShelleyTransactionInput
@@ -250,6 +259,11 @@ func (s *ConwayTransactionInputSet) Items() []shelley.ShelleyTransactionInput {
250259
return s.items
251260
}
252261

262+
func (s *ConwayTransactionInputSet) SetItems(items []shelley.ShelleyTransactionInput) {
263+
s.items = make([]shelley.ShelleyTransactionInput, len(items))
264+
copy(s.items, items)
265+
}
266+
253267
type ConwayTransactionBody struct {
254268
babbage.BabbageTransactionBody
255269
TxInputs ConwayTransactionInputSet `cbor:"0,keyasint,omitempty"`

ledger/conway/errors.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2025 Blink Labs Software
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package conway
16+
17+
import (
18+
"strings"
19+
20+
"github.com/blinklabs-io/gouroboros/ledger/common"
21+
)
22+
23+
type NonDisjointRefInputsError struct {
24+
Inputs []common.TransactionInput
25+
}
26+
27+
func (e NonDisjointRefInputsError) Error() string {
28+
tmpInputs := make([]string, 0, len(e.Inputs))
29+
for idx, tmpInput := range e.Inputs {
30+
tmpInputs[idx] = tmpInput.String()
31+
}
32+
return "non-disjoint reference inputs: " + strings.Join(tmpInputs, ", ")
33+
}

0 commit comments

Comments
 (0)