Skip to content

Commit 2f5c142

Browse files
authored
feat: account for stake/pool deposits in validation rules (#938)
Signed-off-by: Aurora Gaffney <[email protected]>
1 parent c0ca49c commit 2f5c142

File tree

12 files changed

+304
-12
lines changed

12 files changed

+304
-12
lines changed

ledger/allegra/rules.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,16 @@ func UtxoValidateValueNotConservedUtxo(
111111
ls common.LedgerState,
112112
pp common.ProtocolParameters,
113113
) error {
114-
return shelley.UtxoValidateValueNotConservedUtxo(tx, slot, ls, pp)
114+
tmpPparams, ok := pp.(*AllegraProtocolParameters)
115+
if !ok {
116+
return errors.New("pparams are not expected type")
117+
}
118+
return shelley.UtxoValidateValueNotConservedUtxo(
119+
tx,
120+
slot,
121+
ls,
122+
&tmpPparams.ShelleyProtocolParameters,
123+
)
115124
}
116125

117126
func UtxoValidateOutputTooSmallUtxo(

ledger/allegra/rules_test.go

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,7 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) {
528528
testInputTxId := "d228b482a1aae768e4a796380f49e021d9c21f70d3c12cb186b188dedfc0ee22"
529529
var testInputAmount uint64 = 555666777
530530
var testFee uint64 = 123456
531+
var testStakeDeposit uint64 = 2_000_000
531532
testOutputExactAmount := testInputAmount - testFee
532533
testOutputUnderAmount := testOutputExactAmount - 999
533534
testOutputOverAmount := testOutputExactAmount + 999
@@ -558,7 +559,11 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) {
558559
},
559560
}
560561
testSlot := uint64(0)
561-
testProtocolParams := &allegra.AllegraProtocolParameters{}
562+
testProtocolParams := &allegra.AllegraProtocolParameters{
563+
ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{
564+
KeyDeposit: uint(testStakeDeposit),
565+
},
566+
}
562567
// Exact amount
563568
t.Run(
564569
"exact amount",
@@ -578,6 +583,31 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) {
578583
}
579584
},
580585
)
586+
// Stake registration
587+
t.Run(
588+
"stake registration",
589+
func(t *testing.T) {
590+
testTx.Body.TxOutputs[0].OutputAmount = testOutputExactAmount - testStakeDeposit
591+
testTx.Body.TxCertificates = []common.CertificateWrapper{
592+
{
593+
Type: common.CertificateTypeStakeRegistration,
594+
Certificate: &common.StakeRegistrationCertificate{},
595+
},
596+
}
597+
err := allegra.UtxoValidateValueNotConservedUtxo(
598+
testTx,
599+
testSlot,
600+
testLedgerState,
601+
testProtocolParams,
602+
)
603+
if err != nil {
604+
t.Errorf(
605+
"UtxoValidateValueNotConservedUtxo should succeed when inputs and outputs are balanced\n got error: %v",
606+
err,
607+
)
608+
}
609+
},
610+
)
581611
// Output too low
582612
t.Run(
583613
"output too low",

ledger/alonzo/rules.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,11 @@ func UtxoValidateBadInputsUtxo(tx common.Transaction, slot uint64, ls common.Led
198198
}
199199

200200
func UtxoValidateValueNotConservedUtxo(tx common.Transaction, slot uint64, ls common.LedgerState, pp common.ProtocolParameters) error {
201-
return shelley.UtxoValidateValueNotConservedUtxo(tx, slot, ls, pp)
201+
tmpPparams, ok := pp.(*AlonzoProtocolParameters)
202+
if !ok {
203+
return errors.New("pparams are not expected type")
204+
}
205+
return shelley.UtxoValidateValueNotConservedUtxo(tx, slot, ls, &tmpPparams.ShelleyProtocolParameters)
202206
}
203207

204208
func UtxoValidateOutputTooSmallUtxo(tx common.Transaction, slot uint64, ls common.LedgerState, pp common.ProtocolParameters) error {

ledger/alonzo/rules_test.go

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,7 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) {
541541
testInputTxId := "d228b482a1aae768e4a796380f49e021d9c21f70d3c12cb186b188dedfc0ee22"
542542
var testInputAmount uint64 = 555666777
543543
var testFee uint64 = 123456
544+
var testStakeDeposit uint64 = 2_000_000
544545
testOutputExactAmount := testInputAmount - testFee
545546
testOutputUnderAmount := testOutputExactAmount - 999
546547
testOutputOverAmount := testOutputExactAmount + 999
@@ -575,7 +576,15 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) {
575576
},
576577
}
577578
testSlot := uint64(0)
578-
testProtocolParams := &alonzo.AlonzoProtocolParameters{}
579+
testProtocolParams := &alonzo.AlonzoProtocolParameters{
580+
MaryProtocolParameters: mary.MaryProtocolParameters{
581+
AllegraProtocolParameters: allegra.AllegraProtocolParameters{
582+
ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{
583+
KeyDeposit: uint(testStakeDeposit),
584+
},
585+
},
586+
},
587+
}
579588
// Exact amount
580589
t.Run(
581590
"exact amount",
@@ -595,6 +604,31 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) {
595604
}
596605
},
597606
)
607+
// Stake registration
608+
t.Run(
609+
"stake registration",
610+
func(t *testing.T) {
611+
testTx.Body.TxOutputs[0].OutputAmount.Amount = testOutputExactAmount - testStakeDeposit
612+
testTx.Body.TxCertificates = []common.CertificateWrapper{
613+
{
614+
Type: common.CertificateTypeStakeRegistration,
615+
Certificate: &common.StakeRegistrationCertificate{},
616+
},
617+
}
618+
err := alonzo.UtxoValidateValueNotConservedUtxo(
619+
testTx,
620+
testSlot,
621+
testLedgerState,
622+
testProtocolParams,
623+
)
624+
if err != nil {
625+
t.Errorf(
626+
"UtxoValidateValueNotConservedUtxo should succeed when inputs and outputs are balanced\n got error: %v",
627+
err,
628+
)
629+
}
630+
},
631+
)
598632
// Output too low
599633
t.Run(
600634
"output too low",

ledger/babbage/rules.go

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,46 @@ func UtxoValidateBadInputsUtxo(tx common.Transaction, slot uint64, ls common.Led
177177
}
178178

179179
func UtxoValidateValueNotConservedUtxo(tx common.Transaction, slot uint64, ls common.LedgerState, pp common.ProtocolParameters) error {
180-
return shelley.UtxoValidateValueNotConservedUtxo(tx, slot, ls, pp)
180+
tmpPparams, ok := pp.(*BabbageProtocolParameters)
181+
if !ok {
182+
return errors.New("pparams are not expected type")
183+
}
184+
// Calculate consumed value
185+
// consumed = value from input(s) + withdrawals + refunds(?)
186+
var consumedValue uint64
187+
for _, tmpInput := range tx.Inputs() {
188+
tmpUtxo, err := ls.UtxoById(tmpInput)
189+
// Ignore errors fetching the UTxO and exclude it from calculations
190+
if err != nil {
191+
continue
192+
}
193+
consumedValue += tmpUtxo.Output.Amount()
194+
}
195+
for _, tmpWithdrawalAmount := range tx.Withdrawals() {
196+
consumedValue += tmpWithdrawalAmount
197+
}
198+
// Calculate produced value
199+
// produced = value from output(s) + fee + deposits
200+
var producedValue uint64
201+
for _, tmpOutput := range tx.Outputs() {
202+
producedValue += tmpOutput.Amount()
203+
}
204+
producedValue += tx.Fee()
205+
for _, cert := range tx.Certificates() {
206+
switch cert.(type) {
207+
case *common.PoolRegistrationCertificate:
208+
producedValue += uint64(tmpPparams.PoolDeposit)
209+
case *common.StakeRegistrationCertificate:
210+
producedValue += uint64(tmpPparams.KeyDeposit)
211+
}
212+
}
213+
if consumedValue == producedValue {
214+
return nil
215+
}
216+
return shelley.ValueNotConservedUtxoError{
217+
Consumed: consumedValue,
218+
Produced: producedValue,
219+
}
181220
}
182221

183222
func UtxoValidateOutputTooSmallUtxo(tx common.Transaction, slot uint64, ls common.LedgerState, pp common.ProtocolParameters) error {

ledger/babbage/rules_test.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,7 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) {
544544
testInputTxId := "d228b482a1aae768e4a796380f49e021d9c21f70d3c12cb186b188dedfc0ee22"
545545
var testInputAmount uint64 = 555666777
546546
var testFee uint64 = 123456
547+
var testStakeDeposit uint64 = 2_000_000
547548
testOutputExactAmount := testInputAmount - testFee
548549
testOutputUnderAmount := testOutputExactAmount - 999
549550
testOutputOverAmount := testOutputExactAmount + 999
@@ -580,7 +581,9 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) {
580581
},
581582
}
582583
testSlot := uint64(0)
583-
testProtocolParams := &babbage.BabbageProtocolParameters{}
584+
testProtocolParams := &babbage.BabbageProtocolParameters{
585+
KeyDeposit: uint(testStakeDeposit),
586+
}
584587
// Exact amount
585588
t.Run(
586589
"exact amount",
@@ -600,6 +603,31 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) {
600603
}
601604
},
602605
)
606+
// Stake registration
607+
t.Run(
608+
"stake registration",
609+
func(t *testing.T) {
610+
testTx.Body.TxOutputs[0].OutputAmount.Amount = testOutputExactAmount - testStakeDeposit
611+
testTx.Body.TxCertificates = []common.CertificateWrapper{
612+
{
613+
Type: common.CertificateTypeStakeRegistration,
614+
Certificate: &common.StakeRegistrationCertificate{},
615+
},
616+
}
617+
err := babbage.UtxoValidateValueNotConservedUtxo(
618+
testTx,
619+
testSlot,
620+
testLedgerState,
621+
testProtocolParams,
622+
)
623+
if err != nil {
624+
t.Errorf(
625+
"UtxoValidateValueNotConservedUtxo should succeed when inputs and outputs are balanced\n got error: %v",
626+
err,
627+
)
628+
}
629+
},
630+
)
603631
// Output too low
604632
t.Run(
605633
"output too low",

ledger/conway/rules.go

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,46 @@ func UtxoValidateBadInputsUtxo(tx common.Transaction, slot uint64, ls common.Led
173173
}
174174

175175
func UtxoValidateValueNotConservedUtxo(tx common.Transaction, slot uint64, ls common.LedgerState, pp common.ProtocolParameters) error {
176-
return shelley.UtxoValidateValueNotConservedUtxo(tx, slot, ls, pp)
176+
tmpPparams, ok := pp.(*ConwayProtocolParameters)
177+
if !ok {
178+
return errors.New("pparams are not expected type")
179+
}
180+
// Calculate consumed value
181+
// consumed = value from input(s) + withdrawals + refunds(?)
182+
var consumedValue uint64
183+
for _, tmpInput := range tx.Inputs() {
184+
tmpUtxo, err := ls.UtxoById(tmpInput)
185+
// Ignore errors fetching the UTxO and exclude it from calculations
186+
if err != nil {
187+
continue
188+
}
189+
consumedValue += tmpUtxo.Output.Amount()
190+
}
191+
for _, tmpWithdrawalAmount := range tx.Withdrawals() {
192+
consumedValue += tmpWithdrawalAmount
193+
}
194+
// Calculate produced value
195+
// produced = value from output(s) + fee + deposits
196+
var producedValue uint64
197+
for _, tmpOutput := range tx.Outputs() {
198+
producedValue += tmpOutput.Amount()
199+
}
200+
producedValue += tx.Fee()
201+
for _, cert := range tx.Certificates() {
202+
switch cert.(type) {
203+
case *common.PoolRegistrationCertificate:
204+
producedValue += uint64(tmpPparams.PoolDeposit)
205+
case *common.StakeRegistrationCertificate:
206+
producedValue += uint64(tmpPparams.KeyDeposit)
207+
}
208+
}
209+
if consumedValue == producedValue {
210+
return nil
211+
}
212+
return shelley.ValueNotConservedUtxoError{
213+
Consumed: consumedValue,
214+
Produced: producedValue,
215+
}
177216
}
178217

179218
func UtxoValidateOutputTooSmallUtxo(tx common.Transaction, slot uint64, ls common.LedgerState, pp common.ProtocolParameters) error {

ledger/conway/rules_test.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) {
545545
testInputTxId := "d228b482a1aae768e4a796380f49e021d9c21f70d3c12cb186b188dedfc0ee22"
546546
var testInputAmount uint64 = 555666777
547547
var testFee uint64 = 123456
548+
var testStakeDeposit uint64 = 2_000_000
548549
testOutputExactAmount := testInputAmount - testFee
549550
testOutputUnderAmount := testOutputExactAmount - 999
550551
testOutputOverAmount := testOutputExactAmount + 999
@@ -583,7 +584,9 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) {
583584
},
584585
}
585586
testSlot := uint64(0)
586-
testProtocolParams := &conway.ConwayProtocolParameters{}
587+
testProtocolParams := &conway.ConwayProtocolParameters{
588+
KeyDeposit: uint(testStakeDeposit),
589+
}
587590
// Exact amount
588591
t.Run(
589592
"exact amount",
@@ -603,6 +606,31 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) {
603606
}
604607
},
605608
)
609+
// Stake registration
610+
t.Run(
611+
"stake registration",
612+
func(t *testing.T) {
613+
testTx.Body.TxOutputs[0].OutputAmount.Amount = testOutputExactAmount - testStakeDeposit
614+
testTx.Body.TxCertificates = []common.CertificateWrapper{
615+
{
616+
Type: common.CertificateTypeStakeRegistration,
617+
Certificate: &common.StakeRegistrationCertificate{},
618+
},
619+
}
620+
err := conway.UtxoValidateValueNotConservedUtxo(
621+
testTx,
622+
testSlot,
623+
testLedgerState,
624+
testProtocolParams,
625+
)
626+
if err != nil {
627+
t.Errorf(
628+
"UtxoValidateValueNotConservedUtxo should succeed when inputs and outputs are balanced\n got error: %v",
629+
err,
630+
)
631+
}
632+
},
633+
)
606634
// Output too low
607635
t.Run(
608636
"output too low",

ledger/mary/rules.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,16 @@ func UtxoValidateValueNotConservedUtxo(
140140
ls common.LedgerState,
141141
pp common.ProtocolParameters,
142142
) error {
143-
return shelley.UtxoValidateValueNotConservedUtxo(tx, slot, ls, pp)
143+
tmpPparams, ok := pp.(*MaryProtocolParameters)
144+
if !ok {
145+
return errors.New("pparams are not expected type")
146+
}
147+
return shelley.UtxoValidateValueNotConservedUtxo(
148+
tx,
149+
slot,
150+
ls,
151+
&tmpPparams.ShelleyProtocolParameters,
152+
)
144153
}
145154

146155
func UtxoValidateOutputTooSmallUtxo(

0 commit comments

Comments
 (0)