Skip to content

Commit 7ed7244

Browse files
wolf31o2ch1bo
andauthored
test(protocol): localstatequery using cardano blueprint tests (#1001)
Adds cardano-blueprint submodule that contains first examples of local state query query and result data. The included getSystemStart result example was generated using the actual data type used by the haskell server implementation. To make the example roundtrip, big integers (> int64) must be supported. Signed-off-by: Sebastian Nagel <[email protected]> Co-authored-by: Sebastian Nagel <[email protected]>
1 parent 3f16d60 commit 7ed7244

File tree

7 files changed

+115
-5
lines changed

7 files changed

+115
-5
lines changed

.github/workflows/go-test.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ jobs:
2121
runs-on: ${{ matrix.platform }}
2222
steps:
2323
- uses: actions/checkout@v4
24+
with:
25+
submodules: true
2426
- uses: actions/setup-go@v5
2527
with:
2628
go-version: ${{ matrix.go-version }}

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "cardano-blueprint"]
2+
path = cardano-blueprint
3+
url = [email protected]:cardano-scaling/cardano-blueprint

cardano-blueprint

Submodule cardano-blueprint added at e707795

cmd/gouroboros/query.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,9 @@ func testQuery(f *globalFlags) {
124124
os.Exit(1)
125125
}
126126
fmt.Printf(
127-
"system-start: year = %d, day = %d, picoseconds = %d\n",
127+
// REVIEW: %d should work for big/Int, but warns and produces output
128+
// like {%!d(bool=false) [2025]}
129+
"system-start: year = %v, day = %d, picoseconds = %v\n",
128130
systemStart.Year,
129131
systemStart.Day,
130132
systemStart.Picoseconds,

protocol/localstatequery/client_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package localstatequery_test
1717
import (
1818
"encoding/json"
1919
"fmt"
20+
"math/big"
2021
"reflect"
2122
"testing"
2223
"time"
@@ -290,9 +291,9 @@ func TestGetUTxOByAddress(t *testing.T) {
290291
func TestGenesisConfigJSON(t *testing.T) {
291292
genesisConfig := localstatequery.GenesisConfigResult{
292293
Start: localstatequery.SystemStartResult{
293-
Year: 2024,
294+
Year: *big.NewInt(2024),
294295
Day: 35,
295-
Picoseconds: 1234567890123456,
296+
Picoseconds: *big.NewInt(1234567890123456),
296297
},
297298
NetworkMagic: 764824073,
298299
NetworkId: 1,

protocol/localstatequery/messages_test.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ package localstatequery
1616

1717
import (
1818
"encoding/hex"
19+
"fmt"
20+
"math/big"
21+
"os"
1922
"reflect"
2023
"testing"
2124

@@ -28,6 +31,7 @@ type testDefinition struct {
2831
CborHex string
2932
Message protocol.Message
3033
MessageType uint
34+
Result interface{}
3135
}
3236

3337
var tests = []testDefinition{
@@ -92,6 +96,26 @@ var tests = []testDefinition{
9296
Message: NewMsgReAcquireVolatileTip(),
9397
MessageType: MessageTypeReacquireVolatileTip,
9498
},
99+
{
100+
CborHex: string(readFile("../../cardano-blueprint/src/api/examples/getSystemStart/query.cbor")),
101+
Message: NewMsgQuery(&SystemStartQuery{simpleQueryBase{Type: QueryTypeSystemStart}}),
102+
MessageType: MessageTypeQuery,
103+
},
104+
{
105+
CborHex: string(readFile("../../cardano-blueprint/src/api/examples/getSystemStart/result.cbor")),
106+
Message: NewMsgResult(unsafeCbor(
107+
SystemStartResult{
108+
Year: unsafeBigInt([]byte("703941703872597091335551638723343370661404331303175992839224705786473148")),
109+
Day: -4205646576720553090,
110+
Picoseconds: unsafeBigInt([]byte("-554918151390414980540174869115975093799476848534297657333456993160799627")),
111+
})),
112+
MessageType: MessageTypeResult,
113+
Result: SystemStartResult{
114+
Year: unsafeBigInt([]byte("703941703872597091335551638723343370661404331303175992839224705786473148")),
115+
Day: -4205646576720553090,
116+
Picoseconds: unsafeBigInt([]byte("-554918151390414980540174869115975093799476848534297657333456993160799627")),
117+
},
118+
},
95119
}
96120

97121
func TestDecode(t *testing.T) {
@@ -104,6 +128,23 @@ func TestDecode(t *testing.T) {
104128
if err != nil {
105129
t.Fatalf("failed to decode CBOR: %s", err)
106130
}
131+
// cast msg to MsgResult and further try to decode cbor
132+
if m, ok := msg.(*MsgResult); ok && test.Result != nil {
133+
var decoded = reflect.New(reflect.TypeOf(test.Result))
134+
_, err := cbor.Decode(m.Result, decoded.Interface())
135+
if err != nil {
136+
t.Fatalf("failed to decode result: %s", err)
137+
}
138+
var actual = reflect.Indirect(decoded).Interface()
139+
if !reflect.DeepEqual(actual, test.Result) {
140+
t.Fatalf(
141+
"MsgResult content did not decode to expected Result object\n got: %#v\n wanted: %#v",
142+
actual,
143+
test.Result,
144+
)
145+
}
146+
}
147+
107148
// Set the raw CBOR so the comparison should succeed
108149
test.Message.SetCbor(cborData)
109150
if m, ok := msg.(*MsgQuery); ok {
@@ -135,3 +176,30 @@ func TestEncode(t *testing.T) {
135176
}
136177
}
137178
}
179+
180+
// Helper function to encode to cbor or panic
181+
func unsafeCbor(data interface{}) []byte {
182+
cborData, err := cbor.Encode(data)
183+
if err != nil {
184+
panic(fmt.Sprintf("error encoding to CBOR: %s", err))
185+
}
186+
return cborData
187+
}
188+
189+
func unsafeBigInt(text []byte) big.Int {
190+
var i big.Int
191+
err := i.UnmarshalText(text)
192+
if err != nil {
193+
panic(fmt.Sprintf("error unmarshalling text to big.Int: %s", err))
194+
}
195+
return i
196+
}
197+
198+
// Helper function to allow inline reading of a file without capturing the error
199+
func readFile(path string) []byte {
200+
data, err := os.ReadFile(path)
201+
if err != nil {
202+
panic(fmt.Sprintf("error reading file: %s", err))
203+
}
204+
return data
205+
}

protocol/localstatequery/queries.go

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
package localstatequery
1616

1717
import (
18+
"encoding/json"
1819
"fmt"
20+
"math/big"
1921

2022
"github.com/blinklabs-io/gouroboros/cbor"
2123
"github.com/blinklabs-io/gouroboros/ledger"
@@ -416,9 +418,40 @@ type SystemStartQuery struct {
416418
type SystemStartResult struct {
417419
// Tells the CBOR decoder to convert to/from a struct and a CBOR array
418420
_ struct{} `cbor:",toarray"`
419-
Year int
421+
Year big.Int
420422
Day int
421-
Picoseconds uint64
423+
Picoseconds big.Int
424+
}
425+
426+
func (s SystemStartResult) String() string {
427+
return fmt.Sprintf("SystemStart %s %d %s", s.Year.String(), s.Day, s.Picoseconds.String())
428+
}
429+
430+
func (s SystemStartResult) MarshalJSON() ([]byte, error) {
431+
return json.Marshal(struct {
432+
Year string `json:"year"`
433+
Day int `json:"day"`
434+
Picoseconds string `json:"picoseconds"`
435+
}{
436+
Year: s.Year.String(),
437+
Day: s.Day,
438+
Picoseconds: s.Picoseconds.String(),
439+
})
440+
}
441+
442+
func (s *SystemStartResult) UnmarshalJSON(data []byte) error {
443+
var tmp struct {
444+
Year string `json:"year"`
445+
Day int `json:"day"`
446+
Picoseconds string `json:"picoseconds"`
447+
}
448+
if err := json.Unmarshal(data, &tmp); err != nil {
449+
return err
450+
}
451+
s.Year.SetString(tmp.Year, 10)
452+
s.Day = tmp.Day
453+
s.Picoseconds.SetString(tmp.Picoseconds, 10)
454+
return nil
422455
}
423456

424457
type ChainBlockNoQuery struct {

0 commit comments

Comments
 (0)