diff --git a/ledger/common/rules.go b/ledger/common/rules.go index a900fea1..04e96128 100644 --- a/ledger/common/rules.go +++ b/ledger/common/rules.go @@ -14,4 +14,4 @@ package common -type UtxoValidationRuleFunc func(Transaction, LedgerState, TipState, ProtocolParameters) error +type UtxoValidationRuleFunc func(Transaction, uint64, LedgerState, ProtocolParameters) error diff --git a/ledger/shelley/rules.go b/ledger/shelley/rules.go index 9ee9ab1d..5fe90681 100644 --- a/ledger/shelley/rules.go +++ b/ledger/shelley/rules.go @@ -35,23 +35,19 @@ var UtxoValidationRules = []common.UtxoValidationRuleFunc{ } // UtxoValidateTimeToLive ensures that the current tip slot is not after the specified TTL value -func UtxoValidateTimeToLive(tx common.Transaction, ls common.LedgerState, ts common.TipState, pp common.ProtocolParameters) error { - tip, err := ts.Tip() - if err != nil { - return err - } +func UtxoValidateTimeToLive(tx common.Transaction, slot uint64, ls common.LedgerState, pp common.ProtocolParameters) error { ttl := tx.TTL() - if ttl == 0 || ttl >= tip.Point.Slot { + if ttl == 0 || ttl >= slot { return nil } return ExpiredUtxoError{ Ttl: ttl, - Slot: tip.Point.Slot, + Slot: slot, } } // UtxoValidateInputSetEmptyUtxo ensures that the input set is not empty -func UtxoValidateInputSetEmptyUtxo(tx common.Transaction, ls common.LedgerState, ts common.TipState, pp common.ProtocolParameters) error { +func UtxoValidateInputSetEmptyUtxo(tx common.Transaction, slot uint64, ls common.LedgerState, pp common.ProtocolParameters) error { if len(tx.Inputs()) > 0 { return nil } @@ -59,7 +55,7 @@ func UtxoValidateInputSetEmptyUtxo(tx common.Transaction, ls common.LedgerState, } // UtxoValidateFeeTooSmallUtxo ensures that the fee is at least the calculated minimum -func UtxoValidateFeeTooSmallUtxo(tx common.Transaction, ls common.LedgerState, ts common.TipState, pp common.ProtocolParameters) error { +func UtxoValidateFeeTooSmallUtxo(tx common.Transaction, slot uint64, ls common.LedgerState, pp common.ProtocolParameters) error { minFee, err := MinFeeTx(tx, pp) if err != nil { return err @@ -74,7 +70,7 @@ func UtxoValidateFeeTooSmallUtxo(tx common.Transaction, ls common.LedgerState, t } // UtxoValidateBadInputsUtxo ensures that all inputs are present in the ledger state (have not been spent) -func UtxoValidateBadInputsUtxo(tx common.Transaction, ls common.LedgerState, ts common.TipState, pp common.ProtocolParameters) error { +func UtxoValidateBadInputsUtxo(tx common.Transaction, slot uint64, ls common.LedgerState, pp common.ProtocolParameters) error { var badInputs []common.TransactionInput for _, tmpInput := range tx.Inputs() { _, err := ls.UtxoById(tmpInput) @@ -91,7 +87,7 @@ func UtxoValidateBadInputsUtxo(tx common.Transaction, ls common.LedgerState, ts } // UtxoValidateWrongNetwork ensures that all output addresses use the correct network ID -func UtxoValidateWrongNetwork(tx common.Transaction, ls common.LedgerState, ts common.TipState, pp common.ProtocolParameters) error { +func UtxoValidateWrongNetwork(tx common.Transaction, slot uint64, ls common.LedgerState, pp common.ProtocolParameters) error { networkId := ls.NetworkId() var badAddrs []common.Address for _, tmpOutput := range tx.Outputs() { @@ -111,7 +107,7 @@ func UtxoValidateWrongNetwork(tx common.Transaction, ls common.LedgerState, ts c } // UtxoValidateWrongNetworkWithdrawal ensures that all withdrawal addresses use the correct network ID -func UtxoValidateWrongNetworkWithdrawal(tx common.Transaction, ls common.LedgerState, ts common.TipState, pp common.ProtocolParameters) error { +func UtxoValidateWrongNetworkWithdrawal(tx common.Transaction, slot uint64, ls common.LedgerState, pp common.ProtocolParameters) error { networkId := ls.NetworkId() var badAddrs []common.Address for addr := range tx.Withdrawals() { @@ -130,7 +126,7 @@ func UtxoValidateWrongNetworkWithdrawal(tx common.Transaction, ls common.LedgerS } // UtxoValidateValueNotConservedUtxo ensures that the consumed value equals the produced value -func UtxoValidateValueNotConservedUtxo(tx common.Transaction, ls common.LedgerState, ts common.TipState, pp common.ProtocolParameters) error { +func UtxoValidateValueNotConservedUtxo(tx common.Transaction, slot uint64, ls common.LedgerState, pp common.ProtocolParameters) error { // Calculate consumed value // consumed = value from input(s) + withdrawals + refunds(?) var consumedValue uint64 @@ -162,7 +158,7 @@ func UtxoValidateValueNotConservedUtxo(tx common.Transaction, ls common.LedgerSt } // UtxoValidateOutputTooSmallUtxo ensures that outputs have at least the minimum value -func UtxoValidateOutputTooSmallUtxo(tx common.Transaction, ls common.LedgerState, ts common.TipState, pp common.ProtocolParameters) error { +func UtxoValidateOutputTooSmallUtxo(tx common.Transaction, slot uint64, ls common.LedgerState, pp common.ProtocolParameters) error { minCoin, err := MinCoinTxOut(tx, pp) if err != nil { return err @@ -182,7 +178,7 @@ func UtxoValidateOutputTooSmallUtxo(tx common.Transaction, ls common.LedgerState } // UtxoValidateOutputBootAddrAttrsTooBig ensures that bootstrap (Byron) addresses don't have attributes that are too large -func UtxoValidateOutputBootAddrAttrsTooBig(tx common.Transaction, ls common.LedgerState, ts common.TipState, pp common.ProtocolParameters) error { +func UtxoValidateOutputBootAddrAttrsTooBig(tx common.Transaction, slot uint64, ls common.LedgerState, pp common.ProtocolParameters) error { var badOutputs []common.TransactionOutput for _, tmpOutput := range tx.Outputs() { addr := tmpOutput.Address() @@ -208,7 +204,7 @@ func UtxoValidateOutputBootAddrAttrsTooBig(tx common.Transaction, ls common.Ledg } // UtxoValidateMaxTxSizeUtxo ensures that a transaction does not exceed the max size -func UtxoValidateMaxTxSizeUtxo(tx common.Transaction, ls common.LedgerState, ts common.TipState, pp common.ProtocolParameters) error { +func UtxoValidateMaxTxSizeUtxo(tx common.Transaction, slot uint64, ls common.LedgerState, pp common.ProtocolParameters) error { tmpTx, ok := tx.(*ShelleyTransaction) if !ok { return fmt.Errorf("transaction is not expected type") diff --git a/ledger/shelley/rules_test.go b/ledger/shelley/rules_test.go index fe946cf7..9fa833e3 100644 --- a/ledger/shelley/rules_test.go +++ b/ledger/shelley/rules_test.go @@ -22,7 +22,6 @@ import ( "github.com/blinklabs-io/gouroboros/ledger/common" "github.com/blinklabs-io/gouroboros/ledger/shelley" - pcommon "github.com/blinklabs-io/gouroboros/protocol/common" "github.com/stretchr/testify/assert" ) @@ -49,14 +48,6 @@ func (ls testLedgerState) UtxoById(id common.TransactionInput) (common.Utxo, err return common.Utxo{}, fmt.Errorf("not found") } -type testTipState struct { - tip pcommon.Tip -} - -func (ts testTipState) Tip() (pcommon.Tip, error) { - return ts.tip, nil -} - func TestUtxoValidateTimeToLive(t *testing.T) { var testSlot uint64 = 555666777 var testZeroSlot uint64 = 0 @@ -74,17 +65,10 @@ func TestUtxoValidateTimeToLive(t *testing.T) { t.Run( name, func(t *testing.T) { - testTipState := testTipState{ - tip: pcommon.Tip{ - Point: pcommon.Point{ - Slot: testTipSlot, - }, - }, - } err := shelley.UtxoValidateTimeToLive( testTx, + testTipSlot, testLedgerState, - testTipState, testProtocolParams, ) validateFunc(t, err) @@ -177,7 +161,7 @@ func TestUtxoValidateInputSetEmptyUtxo(t *testing.T) { }, } testLedgerState := testLedgerState{} - testTipState := testTipState{} + testSlot := uint64(0) testProtocolParams := &shelley.ShelleyProtocolParameters{} // Non-empty t.Run( @@ -185,8 +169,8 @@ func TestUtxoValidateInputSetEmptyUtxo(t *testing.T) { func(t *testing.T) { err := shelley.UtxoValidateInputSetEmptyUtxo( testTx, + testSlot, testLedgerState, - testTipState, testProtocolParams, ) if err != nil { @@ -204,8 +188,8 @@ func TestUtxoValidateInputSetEmptyUtxo(t *testing.T) { func(t *testing.T) { err := shelley.UtxoValidateInputSetEmptyUtxo( testTx, + testSlot, testLedgerState, - testTipState, testProtocolParams, ) if err == nil { @@ -244,7 +228,7 @@ func TestUtxoValidateFeeTooSmallUtxo(t *testing.T) { MinFeeB: 53, } testLedgerState := testLedgerState{} - testTipState := testTipState{} + testSlot := uint64(0) // Test helper function testRun := func(t *testing.T, name string, testFee uint64, validateFunc func(*testing.T, error)) { t.Run( @@ -254,8 +238,8 @@ func TestUtxoValidateFeeTooSmallUtxo(t *testing.T) { tmpTestTx.Body.TxFee = testFee err := shelley.UtxoValidateFeeTooSmallUtxo( tmpTestTx, + testSlot, testLedgerState, - testTipState, testProtocolParams, ) validateFunc(t, err) @@ -336,7 +320,7 @@ func TestUtxoValidateBadInputsUtxo(t *testing.T) { }, }, } - testTipState := testTipState{} + testSlot := uint64(0) testProtocolParams := &shelley.ShelleyProtocolParameters{} // Good input t.Run( @@ -347,8 +331,8 @@ func TestUtxoValidateBadInputsUtxo(t *testing.T) { ) err := shelley.UtxoValidateBadInputsUtxo( testTx, + testSlot, testLedgerState, - testTipState, testProtocolParams, ) if err != nil { @@ -368,8 +352,8 @@ func TestUtxoValidateBadInputsUtxo(t *testing.T) { ) err := shelley.UtxoValidateBadInputsUtxo( testTx, + testSlot, testLedgerState, - testTipState, testProtocolParams, ) if err == nil { @@ -406,7 +390,7 @@ func TestUtxoValidateWrongNetwork(t *testing.T) { testLedgerState := testLedgerState{ networkId: common.AddressNetworkMainnet, } - testTipState := testTipState{} + testSlot := uint64(0) testProtocolParams := &shelley.ShelleyProtocolParameters{} // Correct network t.Run( @@ -415,8 +399,8 @@ func TestUtxoValidateWrongNetwork(t *testing.T) { testTx.Body.TxOutputs[0].OutputAddress = testCorrectNetworkAddr err := shelley.UtxoValidateBadInputsUtxo( testTx, + testSlot, testLedgerState, - testTipState, testProtocolParams, ) if err != nil { @@ -434,8 +418,8 @@ func TestUtxoValidateWrongNetwork(t *testing.T) { testTx.Body.TxOutputs[0].OutputAddress = testWrongNetworkAddr err := shelley.UtxoValidateWrongNetwork( testTx, + testSlot, testLedgerState, - testTipState, testProtocolParams, ) if err == nil { @@ -468,7 +452,7 @@ func TestUtxoValidateWrongNetworkWithdrawal(t *testing.T) { testLedgerState := testLedgerState{ networkId: common.AddressNetworkMainnet, } - testTipState := testTipState{} + testSlot := uint64(0) testProtocolParams := &shelley.ShelleyProtocolParameters{} // Correct network t.Run( @@ -477,8 +461,8 @@ func TestUtxoValidateWrongNetworkWithdrawal(t *testing.T) { testTx.Body.TxWithdrawals[&testCorrectNetworkAddr] = 123456 err := shelley.UtxoValidateWrongNetworkWithdrawal( testTx, + testSlot, testLedgerState, - testTipState, testProtocolParams, ) if err != nil { @@ -496,8 +480,8 @@ func TestUtxoValidateWrongNetworkWithdrawal(t *testing.T) { testTx.Body.TxWithdrawals[&testWrongNetworkAddr] = 123456 err := shelley.UtxoValidateWrongNetworkWithdrawal( testTx, + testSlot, testLedgerState, - testTipState, testProtocolParams, ) if err == nil { @@ -550,7 +534,7 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) { }, }, } - testTipState := testTipState{} + testSlot := uint64(0) testProtocolParams := &shelley.ShelleyProtocolParameters{} // Exact amount t.Run( @@ -559,8 +543,8 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) { testTx.Body.TxOutputs[0].OutputAmount = testOutputExactAmount err := shelley.UtxoValidateValueNotConservedUtxo( testTx, + testSlot, testLedgerState, - testTipState, testProtocolParams, ) if err != nil { @@ -578,8 +562,8 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) { testTx.Body.TxOutputs[0].OutputAmount = testOutputUnderAmount err := shelley.UtxoValidateValueNotConservedUtxo( testTx, + testSlot, testLedgerState, - testTipState, testProtocolParams, ) if err == nil { @@ -606,8 +590,8 @@ func TestUtxoValidateValueNotConservedUtxo(t *testing.T) { testTx.Body.TxOutputs[0].OutputAmount = testOutputOverAmount err := shelley.UtxoValidateValueNotConservedUtxo( testTx, + testSlot, testLedgerState, - testTipState, testProtocolParams, ) if err == nil { @@ -641,7 +625,7 @@ func TestUtxoValidateOutputTooSmallUtxo(t *testing.T) { }, } testLedgerState := testLedgerState{} - testTipState := testTipState{} + testSlot := uint64(0) testProtocolParams := &shelley.ShelleyProtocolParameters{ MinUtxoValue: 100000, } @@ -652,8 +636,8 @@ func TestUtxoValidateOutputTooSmallUtxo(t *testing.T) { testTx.Body.TxOutputs[0].OutputAmount = testOutputAmountGood err := shelley.UtxoValidateOutputTooSmallUtxo( testTx, + testSlot, testLedgerState, - testTipState, testProtocolParams, ) if err != nil { @@ -671,8 +655,8 @@ func TestUtxoValidateOutputTooSmallUtxo(t *testing.T) { testTx.Body.TxOutputs[0].OutputAmount = testOutputAmountBad err := shelley.UtxoValidateOutputTooSmallUtxo( testTx, + testSlot, testLedgerState, - testTipState, testProtocolParams, ) if err == nil { @@ -722,7 +706,7 @@ func TestUtxoValidateOutputBootAddrAttrsTooBig(t *testing.T) { }, } testLedgerState := testLedgerState{} - testTipState := testTipState{} + testSlot := uint64(0) testProtocolParams := &shelley.ShelleyProtocolParameters{} // Good t.Run( @@ -731,8 +715,8 @@ func TestUtxoValidateOutputBootAddrAttrsTooBig(t *testing.T) { testTx.Body.TxOutputs[0].OutputAddress = testGoodAddr err := shelley.UtxoValidateOutputBootAddrAttrsTooBig( testTx, + testSlot, testLedgerState, - testTipState, testProtocolParams, ) if err != nil { @@ -750,8 +734,8 @@ func TestUtxoValidateOutputBootAddrAttrsTooBig(t *testing.T) { testTx.Body.TxOutputs[0].OutputAddress = testBadAddr err := shelley.UtxoValidateOutputBootAddrAttrsTooBig( testTx, + testSlot, testLedgerState, - testTipState, testProtocolParams, ) if err == nil { @@ -778,7 +762,7 @@ func TestUtxoValidateMaxTxSizeUtxo(t *testing.T) { var testMaxTxSizeLarge uint = 64 * 1024 testTx := &shelley.ShelleyTransaction{} testLedgerState := testLedgerState{} - testTipState := testTipState{} + testSlot := uint64(0) testProtocolParams := &shelley.ShelleyProtocolParameters{} // Transaction under limit t.Run( @@ -787,8 +771,8 @@ func TestUtxoValidateMaxTxSizeUtxo(t *testing.T) { testProtocolParams.MaxTxSize = testMaxTxSizeLarge err := shelley.UtxoValidateMaxTxSizeUtxo( testTx, + testSlot, testLedgerState, - testTipState, testProtocolParams, ) if err != nil { @@ -806,8 +790,8 @@ func TestUtxoValidateMaxTxSizeUtxo(t *testing.T) { testProtocolParams.MaxTxSize = testMaxTxSizeSmall err := shelley.UtxoValidateMaxTxSizeUtxo( testTx, + testSlot, testLedgerState, - testTipState, testProtocolParams, ) if err == nil {