diff --git a/ledger/allegra/allegra.go b/ledger/allegra/allegra.go index df13f6bd..fb5084e9 100644 --- a/ledger/allegra/allegra.go +++ b/ledger/allegra/allegra.go @@ -308,14 +308,6 @@ func (t *AllegraTransaction) Cbor() []byte { return cborData } -type AllegraProtocolParameters struct { - shelley.ShelleyProtocolParameters -} - -type AllegraProtocolParameterUpdate struct { - shelley.ShelleyProtocolParameterUpdate -} - func NewAllegraBlockFromCbor(data []byte) (*AllegraBlock, error) { var allegraBlock AllegraBlock if _, err := cbor.Decode(data, &allegraBlock); err != nil { diff --git a/ledger/allegra/pparams.go b/ledger/allegra/pparams.go new file mode 100644 index 00000000..4c255df7 --- /dev/null +++ b/ledger/allegra/pparams.go @@ -0,0 +1,31 @@ +// Copyright 2024 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 allegra + +import "github.com/blinklabs-io/gouroboros/ledger/shelley" + +type AllegraProtocolParameters struct { + shelley.ShelleyProtocolParameters +} + +func (p *AllegraProtocolParameters) Update(paramUpdate *AllegraProtocolParameterUpdate) { + p.ShelleyProtocolParameters.Update( + ¶mUpdate.ShelleyProtocolParameterUpdate, + ) +} + +type AllegraProtocolParameterUpdate struct { + shelley.ShelleyProtocolParameterUpdate +} diff --git a/ledger/allegra/pparams_test.go b/ledger/allegra/pparams_test.go new file mode 100644 index 00000000..a73f008e --- /dev/null +++ b/ledger/allegra/pparams_test.go @@ -0,0 +1,76 @@ +// Copyright 2024 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 allegra_test + +import ( + "encoding/hex" + "math/big" + "reflect" + "testing" + + "github.com/blinklabs-io/gouroboros/cbor" + "github.com/blinklabs-io/gouroboros/ledger/allegra" + "github.com/blinklabs-io/gouroboros/ledger/shelley" +) + +func TestAllegraProtocolParamsUpdate(t *testing.T) { + testDefs := []struct { + startParams allegra.AllegraProtocolParameters + updateCbor string + expectedParams allegra.AllegraProtocolParameters + }{ + { + startParams: allegra.AllegraProtocolParameters{ + ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ + Decentralization: &cbor.Rat{Rat: new(big.Rat).SetInt64(1)}, + }, + }, + updateCbor: "a10cd81e82090a", + expectedParams: allegra.AllegraProtocolParameters{ + ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ + Decentralization: &cbor.Rat{Rat: big.NewRat(9, 10)}, + }, + }, + }, + { + startParams: allegra.AllegraProtocolParameters{ + ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ + ProtocolMajor: 3, + }, + }, + updateCbor: "a10e820400", + expectedParams: allegra.AllegraProtocolParameters{ + ShelleyProtocolParameters: shelley.ShelleyProtocolParameters{ + ProtocolMajor: 4, + }, + }, + }, + } + for _, testDef := range testDefs { + cborBytes, err := hex.DecodeString(testDef.updateCbor) + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + var tmpUpdate allegra.AllegraProtocolParameterUpdate + if _, err := cbor.Decode(cborBytes, &tmpUpdate); err != nil { + t.Fatalf("unexpected error: %s", err) + } + tmpParams := testDef.startParams + tmpParams.Update(&tmpUpdate) + if !reflect.DeepEqual(tmpParams, testDef.expectedParams) { + t.Fatalf("did not get expected params:\n got: %#v\n wanted: %#v", tmpParams, testDef.expectedParams) + } + } +} diff --git a/ledger/common/pparams.go b/ledger/common/pparams.go index 2a6ac564..1b3abfd1 100644 --- a/ledger/common/pparams.go +++ b/ledger/common/pparams.go @@ -14,7 +14,50 @@ package common +import ( + "fmt" + + "github.com/blinklabs-io/gouroboros/cbor" +) + type ProtocolParameterUpdate interface { IsProtocolParameterUpdate() Cbor() []byte } + +const ( + NonceType0 = 0 + NonceType1 = 1 +) + +var NeutralNonce = Nonce{ + Type: NonceType0, +} + +type Nonce struct { + cbor.StructAsArray + Type uint + Value [32]byte +} + +func (n *Nonce) UnmarshalCBOR(data []byte) error { + nonceType, err := cbor.DecodeIdFromList(data) + if err != nil { + return err + } + + n.Type = uint(nonceType) + + switch nonceType { + case NonceType0: + // Value uses default value + case NonceType1: + if err := cbor.DecodeGeneric(data, n); err != nil { + fmt.Printf("Nonce decode error: %+v\n", data) + return err + } + default: + return fmt.Errorf("unsupported nonce type %d", nonceType) + } + return nil +} diff --git a/ledger/common/pparams_test.go b/ledger/common/pparams_test.go new file mode 100644 index 00000000..95aab404 --- /dev/null +++ b/ledger/common/pparams_test.go @@ -0,0 +1,57 @@ +// Copyright 2024 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 common_test + +import ( + "testing" + + "github.com/blinklabs-io/gouroboros/ledger/common" +) + +func TestNonceUnmarshalCBOR(t *testing.T) { + testCases := []struct { + name string + data []byte + expectedErr string + }{ + { + name: "NonceType0", + data: []byte{0x81, 0x00}, + }, + { + name: "NonceType1", + data: []byte{0x82, 0x01, 0x42, 0x01, 0x02}, + }, + { + name: "UnsupportedNonceType", + data: []byte{0x82, 0x02}, + expectedErr: "unsupported nonce type 2", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + n := &common.Nonce{} + err := n.UnmarshalCBOR(tc.data) + if err != nil { + if tc.expectedErr == "" || err.Error() != tc.expectedErr { + t.Errorf("unexpected error: %v", err) + } + } else if tc.expectedErr != "" { + t.Errorf("expected error: %v, got nil", tc.expectedErr) + } + }) + } +} diff --git a/ledger/shelley/pparams.go b/ledger/shelley/pparams.go index 3dc9e0cc..39f16248 100644 --- a/ledger/shelley/pparams.go +++ b/ledger/shelley/pparams.go @@ -15,10 +15,10 @@ package shelley import ( - "fmt" "math/big" "github.com/blinklabs-io/gouroboros/cbor" + "github.com/blinklabs-io/gouroboros/ledger/common" ) type ShelleyProtocolParameters struct { @@ -36,7 +36,7 @@ type ShelleyProtocolParameters struct { Rho *cbor.Rat Tau *cbor.Rat Decentralization *cbor.Rat - Nonce *Nonce + Nonce *common.Nonce ProtocolMajor uint ProtocolMinor uint MinUtxoValue uint @@ -145,7 +145,7 @@ type ShelleyProtocolParameterUpdate struct { Rho *cbor.Rat `cbor:"10,keyasint"` Tau *cbor.Rat `cbor:"11,keyasint"` Decentralization *cbor.Rat `cbor:"12,keyasint"` - Nonce *Nonce `cbor:"13,keyasint"` + Nonce *common.Nonce `cbor:"13,keyasint"` ProtocolVersion *ShelleyProtocolParametersProtocolVersion `cbor:"14,keyasint"` MinUtxoValue *uint `cbor:"15,keyasint"` } @@ -155,40 +155,3 @@ func (ShelleyProtocolParameterUpdate) IsProtocolParameterUpdate() {} func (u *ShelleyProtocolParameterUpdate) UnmarshalCBOR(data []byte) error { return u.UnmarshalCbor(data, u) } - -const ( - NonceType0 = 0 - NonceType1 = 1 -) - -var NeutralNonce = Nonce{ - Type: NonceType0, -} - -type Nonce struct { - cbor.StructAsArray - Type uint - Value [32]byte -} - -func (n *Nonce) UnmarshalCBOR(data []byte) error { - nonceType, err := cbor.DecodeIdFromList(data) - if err != nil { - return err - } - - n.Type = uint(nonceType) - - switch nonceType { - case NonceType0: - // Value uses default value - case NonceType1: - if err := cbor.DecodeGeneric(data, n); err != nil { - fmt.Printf("Nonce decode error: %+v\n", data) - return err - } - default: - return fmt.Errorf("unsupported nonce type %d", nonceType) - } - return nil -} diff --git a/ledger/shelley/pparams_test.go b/ledger/shelley/pparams_test.go index 45ef01ed..47da504a 100644 --- a/ledger/shelley/pparams_test.go +++ b/ledger/shelley/pparams_test.go @@ -25,42 +25,6 @@ import ( "github.com/blinklabs-io/gouroboros/ledger/shelley" ) -func TestNonceUnmarshalCBOR(t *testing.T) { - testCases := []struct { - name string - data []byte - expectedErr string - }{ - { - name: "NonceType0", - data: []byte{0x81, 0x00}, - }, - { - name: "NonceType1", - data: []byte{0x82, 0x01, 0x42, 0x01, 0x02}, - }, - { - name: "UnsupportedNonceType", - data: []byte{0x82, 0x02}, - expectedErr: "unsupported nonce type 2", - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - n := &shelley.Nonce{} - err := n.UnmarshalCBOR(tc.data) - if err != nil { - if tc.expectedErr == "" || err.Error() != tc.expectedErr { - t.Errorf("unexpected error: %v", err) - } - } else if tc.expectedErr != "" { - t.Errorf("expected error: %v, got nil", tc.expectedErr) - } - }) - } -} - func TestShelleyProtocolParamsUpdate(t *testing.T) { testDefs := []struct { startParams shelley.ShelleyProtocolParameters