Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions internal/test/ledger/ledger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2025 Blink Labs Software
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package test_ledger

import (
"errors"

"github.com/blinklabs-io/gouroboros/ledger/common"
)

type MockLedgerState struct {
MockNetworkId uint
MockUtxos []common.Utxo
MockStakeRegistration []common.StakeRegistrationCertificate
MockPoolRegistration []common.PoolRegistrationCertificate
}

func (ls MockLedgerState) NetworkId() uint {
return ls.MockNetworkId
}

func (ls MockLedgerState) UtxoById(
id common.TransactionInput,
) (common.Utxo, error) {
for _, tmpUtxo := range ls.MockUtxos {
if id.Index() != tmpUtxo.Id.Index() {
continue
}
if string(id.Id().Bytes()) != string(tmpUtxo.Id.Id().Bytes()) {
continue
}
return tmpUtxo, nil
}
return common.Utxo{}, errors.New("not found")
}

func (ls MockLedgerState) StakeRegistration(stakingKey []byte) ([]common.StakeRegistrationCertificate, error) {
ret := []common.StakeRegistrationCertificate{}
for _, cert := range ls.MockStakeRegistration {
if string(cert.StakeRegistration.Credential) == string(stakingKey) {
ret = append(ret, cert)
}
}
return ret, nil
}

func (ls MockLedgerState) PoolRegistration(poolKeyHash []byte) ([]common.PoolRegistrationCertificate, error) {
ret := []common.PoolRegistrationCertificate{}
for _, cert := range ls.MockPoolRegistration {
if string(common.Blake2b224(cert.Operator).Bytes()) == string(poolKeyHash) {
ret = append(ret, cert)
}
}
return ret, nil
}
104 changes: 61 additions & 43 deletions ledger/allegra/rules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,40 +17,16 @@ package allegra_test
import (
"crypto/rand"
"encoding/hex"
"errors"
"testing"

test "github.com/blinklabs-io/gouroboros/internal/test/ledger"
"github.com/blinklabs-io/gouroboros/ledger/allegra"
"github.com/blinklabs-io/gouroboros/ledger/common"
"github.com/blinklabs-io/gouroboros/ledger/shelley"

"github.com/stretchr/testify/assert"
)

type testLedgerState struct {
networkId uint
utxos []common.Utxo
}

func (ls testLedgerState) NetworkId() uint {
return ls.networkId
}

func (ls testLedgerState) UtxoById(
id common.TransactionInput,
) (common.Utxo, error) {
for _, tmpUtxo := range ls.utxos {
if id.Index() != tmpUtxo.Id.Index() {
continue
}
if string(id.Id().Bytes()) != string(tmpUtxo.Id.Id().Bytes()) {
continue
}
return tmpUtxo, nil
}
return common.Utxo{}, errors.New("not found")
}

func TestUtxoValidateOutsideValidityIntervalUtxo(t *testing.T) {
var testSlot uint64 = 555666777
var testZeroSlot uint64 = 0
Expand All @@ -59,7 +35,7 @@ func TestUtxoValidateOutsideValidityIntervalUtxo(t *testing.T) {
TxValidityIntervalStart: testSlot,
},
}
testLedgerState := testLedgerState{}
testLedgerState := test.MockLedgerState{}
testProtocolParams := &allegra.AllegraProtocolParameters{}
var testBeforeSlot uint64 = 555666700
var testAfterSlot uint64 = 555666799
Expand Down Expand Up @@ -165,7 +141,7 @@ func TestUtxoValidateInputSetEmptyUtxo(t *testing.T) {
},
},
}
testLedgerState := testLedgerState{}
testLedgerState := test.MockLedgerState{}
testSlot := uint64(0)
testProtocolParams := &allegra.AllegraProtocolParameters{}
// Non-empty
Expand Down Expand Up @@ -236,7 +212,7 @@ func TestUtxoValidateFeeTooSmallUtxo(t *testing.T) {
MinFeeB: 53,
},
}
testLedgerState := testLedgerState{}
testLedgerState := test.MockLedgerState{}
testSlot := uint64(0)
// Test helper function
testRun := func(t *testing.T, name string, testFee uint64, validateFunc func(*testing.T, error)) {
Expand Down Expand Up @@ -322,8 +298,8 @@ func TestUtxoValidateBadInputsUtxo(t *testing.T) {
testTx := &allegra.AllegraTransaction{
Body: allegra.AllegraTransactionBody{},
}
testLedgerState := testLedgerState{
utxos: []common.Utxo{
testLedgerState := test.MockLedgerState{
MockUtxos: []common.Utxo{
{
Id: testGoodInput,
},
Expand Down Expand Up @@ -402,8 +378,8 @@ func TestUtxoValidateWrongNetwork(t *testing.T) {
},
},
}
testLedgerState := testLedgerState{
networkId: common.AddressNetworkMainnet,
testLedgerState := test.MockLedgerState{
MockNetworkId: common.AddressNetworkMainnet,
}
testSlot := uint64(0)
testProtocolParams := &allegra.AllegraProtocolParameters{}
Expand Down Expand Up @@ -470,8 +446,8 @@ func TestUtxoValidateWrongNetworkWithdrawal(t *testing.T) {
},
},
}
testLedgerState := testLedgerState{
networkId: common.AddressNetworkMainnet,
testLedgerState := test.MockLedgerState{
MockNetworkId: common.AddressNetworkMainnet,
}
testSlot := uint64(0)
testProtocolParams := &allegra.AllegraProtocolParameters{}
Expand Down Expand Up @@ -529,6 +505,8 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) {
var testInputAmount uint64 = 555666777
var testFee uint64 = 123456
var testStakeDeposit uint64 = 2_000_000
var testStakeCred1 = []byte{0x01, 0x23, 0x45}
var testStakeCred2 = []byte{0xab, 0xcd, 0xef}
testOutputExactAmount := testInputAmount - testFee
testOutputUnderAmount := testOutputExactAmount - 999
testOutputOverAmount := testOutputExactAmount + 999
Expand All @@ -548,15 +526,22 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) {
},
},
}
testLedgerState := testLedgerState{
utxos: []common.Utxo{
testLedgerState := test.MockLedgerState{
MockUtxos: []common.Utxo{
{
Id: shelley.NewShelleyTransactionInput(testInputTxId, 0),
Output: shelley.ShelleyTransactionOutput{
OutputAmount: testInputAmount,
},
},
},
MockStakeRegistration: []common.StakeRegistrationCertificate{
{
StakeRegistration: common.StakeCredential{
Credential: testStakeCred2,
},
},
},
}
testSlot := uint64(0)
testProtocolParams := &allegra.AllegraProtocolParameters{
Expand All @@ -583,15 +568,48 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) {
}
},
)
// Stake registration
// First stake registration
t.Run(
"stake registration",
"first stake registration",
func(t *testing.T) {
testTx.Body.TxOutputs[0].OutputAmount = testOutputExactAmount - testStakeDeposit
testTx.Body.TxCertificates = []common.CertificateWrapper{
{
Type: common.CertificateTypeStakeRegistration,
Certificate: &common.StakeRegistrationCertificate{},
Type: common.CertificateTypeStakeRegistration,
Certificate: &common.StakeRegistrationCertificate{
StakeRegistration: common.StakeCredential{
Credential: testStakeCred1,
},
},
},
}
err := allegra.UtxoValidateValueNotConservedUtxo(
testTx,
testSlot,
testLedgerState,
testProtocolParams,
)
if err != nil {
t.Errorf(
"UtxoValidateValueNotConservedUtxo should succeed when inputs and outputs are balanced\n got error: %v",
err,
)
}
},
)
// Second stake registration
t.Run(
"second stake registration",
func(t *testing.T) {
testTx.Body.TxOutputs[0].OutputAmount = testOutputExactAmount
testTx.Body.TxCertificates = []common.CertificateWrapper{
{
Type: common.CertificateTypeStakeRegistration,
Certificate: &common.StakeRegistrationCertificate{
StakeRegistration: common.StakeCredential{
Credential: testStakeCred2,
},
},
},
}
err := allegra.UtxoValidateValueNotConservedUtxo(
Expand Down Expand Up @@ -679,7 +697,7 @@ func TestUtxoValidateOutputTooSmallUtxo(t *testing.T) {
},
},
}
testLedgerState := testLedgerState{}
testLedgerState := test.MockLedgerState{}
testSlot := uint64(0)
testProtocolParams := &allegra.AllegraProtocolParameters{
ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{
Expand Down Expand Up @@ -766,7 +784,7 @@ func TestUtxoValidateOutputBootAddrAttrsTooBig(t *testing.T) {
},
},
}
testLedgerState := testLedgerState{}
testLedgerState := test.MockLedgerState{}
testSlot := uint64(0)
testProtocolParams := &allegra.AllegraProtocolParameters{}
// Good
Expand Down Expand Up @@ -822,7 +840,7 @@ func TestUtxoValidateMaxTxSizeUtxo(t *testing.T) {
var testMaxTxSizeSmall uint = 2
var testMaxTxSizeLarge uint = 64 * 1024
testTx := &allegra.AllegraTransaction{}
testLedgerState := testLedgerState{}
testLedgerState := test.MockLedgerState{}
testSlot := uint64(0)
testProtocolParams := &allegra.AllegraProtocolParameters{}
// Transaction under limit
Expand Down
Loading
Loading