Skip to content

Commit 3b41be6

Browse files
s1nafjl
authored andcommitted
graphql: fixes missing tx logs (#25745)
* graphql: fix tx logs * graphql: refactor test service setup * graphql: add test for tx logs
1 parent d0dc349 commit 3b41be6

File tree

3 files changed

+124
-114
lines changed

3 files changed

+124
-114
lines changed

graphql/graphql.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ func (t *Transaction) getLogs(ctx context.Context) (*[]*Log, error) {
481481
}
482482
var ret []*Log
483483
// Select tx logs from all block logs
484-
ix := sort.Search(len(logs), func(i int) bool { return uint64(logs[i].TxIndex) == t.index })
484+
ix := sort.Search(len(logs), func(i int) bool { return uint64(logs[i].TxIndex) >= t.index })
485485
for ix < len(logs) && uint64(logs[ix].TxIndex) == t.index {
486486
ret = append(ret, &Log{
487487
r: t.r,

graphql/graphql_test.go

Lines changed: 118 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package graphql
1818

1919
import (
20+
"context"
21+
"encoding/json"
2022
"fmt"
2123
"io"
2224
"math/big"
@@ -51,15 +53,21 @@ func TestBuildSchema(t *testing.T) {
5153
}
5254
defer stack.Close()
5355
// Make sure the schema can be parsed and matched up to the object model.
54-
if err := newHandler(stack, nil, nil, []string{}, []string{}); err != nil {
56+
if _, err := newHandler(stack, nil, nil, []string{}, []string{}); err != nil {
5557
t.Errorf("Could not construct GraphQL handler: %v", err)
5658
}
5759
}
5860

5961
// Tests that a graphQL request is successfully handled when graphql is enabled on the specified endpoint
6062
func TestGraphQLBlockSerialization(t *testing.T) {
61-
stack := createNode(t, true, false)
63+
stack := createNode(t)
6264
defer stack.Close()
65+
genesis := &core.Genesis{
66+
Config: params.AllEthashProtocolChanges,
67+
GasLimit: 11500000,
68+
Difficulty: big.NewInt(1048576),
69+
}
70+
newGQLService(t, stack, genesis, 10, func(i int, gen *core.BlockGen) {})
6371
// start node
6472
if err := stack.Start(); err != nil {
6573
t.Fatalf("could not start node: %v", err)
@@ -161,8 +169,55 @@ func TestGraphQLBlockSerialization(t *testing.T) {
161169
}
162170

163171
func TestGraphQLBlockSerializationEIP2718(t *testing.T) {
164-
stack := createNode(t, true, true)
172+
// Account for signing txes
173+
var (
174+
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
175+
address = crypto.PubkeyToAddress(key.PublicKey)
176+
funds = big.NewInt(1000000000000000)
177+
dad = common.HexToAddress("0x0000000000000000000000000000000000000dad")
178+
)
179+
stack := createNode(t)
165180
defer stack.Close()
181+
genesis := &core.Genesis{
182+
Config: params.AllEthashProtocolChanges,
183+
GasLimit: 11500000,
184+
Difficulty: big.NewInt(1048576),
185+
Alloc: core.GenesisAlloc{
186+
address: {Balance: funds},
187+
// The address 0xdad sloads 0x00 and 0x01
188+
dad: {
189+
Code: []byte{byte(vm.PC), byte(vm.PC), byte(vm.SLOAD), byte(vm.SLOAD)},
190+
Nonce: 0,
191+
Balance: big.NewInt(0),
192+
},
193+
},
194+
BaseFee: big.NewInt(params.InitialBaseFee),
195+
}
196+
signer := types.LatestSigner(genesis.Config)
197+
newGQLService(t, stack, genesis, 1, func(i int, gen *core.BlockGen) {
198+
gen.SetCoinbase(common.Address{1})
199+
tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{
200+
Nonce: uint64(0),
201+
To: &dad,
202+
Value: big.NewInt(100),
203+
Gas: 50000,
204+
GasPrice: big.NewInt(params.InitialBaseFee),
205+
})
206+
gen.AddTx(tx)
207+
tx, _ = types.SignNewTx(key, signer, &types.AccessListTx{
208+
ChainID: genesis.Config.ChainID,
209+
Nonce: uint64(1),
210+
To: &dad,
211+
Gas: 30000,
212+
GasPrice: big.NewInt(params.InitialBaseFee),
213+
Value: big.NewInt(50),
214+
AccessList: types.AccessList{{
215+
Address: dad,
216+
StorageKeys: []common.Hash{{0}},
217+
}},
218+
})
219+
gen.AddTx(tx)
220+
})
166221
// start node
167222
if err := stack.Start(); err != nil {
168223
t.Fatalf("could not start node: %v", err)
@@ -198,7 +253,7 @@ func TestGraphQLBlockSerializationEIP2718(t *testing.T) {
198253

199254
// Tests that a graphQL request is not handled successfully when graphql is not enabled on the specified endpoint
200255
func TestGraphQLHTTPOnSamePort_GQLRequest_Unsuccessful(t *testing.T) {
201-
stack := createNode(t, false, false)
256+
stack := createNode(t)
202257
defer stack.Close()
203258
if err := stack.Start(); err != nil {
204259
t.Fatalf("could not start node: %v", err)
@@ -212,7 +267,59 @@ func TestGraphQLHTTPOnSamePort_GQLRequest_Unsuccessful(t *testing.T) {
212267
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
213268
}
214269

215-
func createNode(t *testing.T, gqlEnabled bool, txEnabled bool) *node.Node {
270+
func TestGraphQLTransactionLogs(t *testing.T) {
271+
var (
272+
key, _ = crypto.GenerateKey()
273+
addr = crypto.PubkeyToAddress(key.PublicKey)
274+
dadStr = "0x0000000000000000000000000000000000000dad"
275+
dad = common.HexToAddress(dadStr)
276+
genesis = &core.Genesis{
277+
Config: params.AllEthashProtocolChanges,
278+
GasLimit: 11500000,
279+
Difficulty: big.NewInt(1048576),
280+
Alloc: core.GenesisAlloc{
281+
addr: {Balance: big.NewInt(params.Ether)},
282+
dad: {
283+
// LOG0(0, 0), LOG0(0, 0), RETURN(0, 0)
284+
Code: common.Hex2Bytes("60006000a060006000a060006000f3"),
285+
Nonce: 0,
286+
Balance: big.NewInt(0),
287+
},
288+
},
289+
}
290+
signer = types.LatestSigner(genesis.Config)
291+
stack = createNode(t)
292+
)
293+
defer stack.Close()
294+
295+
handler := newGQLService(t, stack, genesis, 1, func(i int, gen *core.BlockGen) {
296+
tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{To: &dad, Gas: 100000, GasPrice: big.NewInt(params.InitialBaseFee)})
297+
gen.AddTx(tx)
298+
tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{To: &dad, Nonce: 1, Gas: 100000, GasPrice: big.NewInt(params.InitialBaseFee)})
299+
gen.AddTx(tx)
300+
tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{To: &dad, Nonce: 2, Gas: 100000, GasPrice: big.NewInt(params.InitialBaseFee)})
301+
gen.AddTx(tx)
302+
})
303+
// start node
304+
if err := stack.Start(); err != nil {
305+
t.Fatalf("could not start node: %v", err)
306+
}
307+
query := `{block { transactions { logs { account { address } } } } }`
308+
res := handler.Schema.Exec(context.Background(), query, "", map[string]interface{}{})
309+
if res.Errors != nil {
310+
t.Fatalf("graphql query failed: %v", res.Errors)
311+
}
312+
have, err := json.Marshal(res.Data)
313+
if err != nil {
314+
t.Fatalf("failed to encode graphql response: %s", err)
315+
}
316+
want := fmt.Sprintf(`{"block":{"transactions":[{"logs":[{"account":{"address":"%s"}},{"account":{"address":"%s"}}]},{"logs":[{"account":{"address":"%s"}},{"account":{"address":"%s"}}]},{"logs":[{"account":{"address":"%s"}},{"account":{"address":"%s"}}]}]}}`, dadStr, dadStr, dadStr, dadStr, dadStr, dadStr)
317+
if string(have) != want {
318+
t.Errorf("response unmatch. expected %s, got %s", want, have)
319+
}
320+
}
321+
322+
func createNode(t *testing.T) *node.Node {
216323
stack, err := node.New(&node.Config{
217324
HTTPHost: "127.0.0.1",
218325
HTTPPort: 0,
@@ -222,83 +329,12 @@ func createNode(t *testing.T, gqlEnabled bool, txEnabled bool) *node.Node {
222329
if err != nil {
223330
t.Fatalf("could not create node: %v", err)
224331
}
225-
if !gqlEnabled {
226-
return stack
227-
}
228-
if !txEnabled {
229-
createGQLService(t, stack)
230-
} else {
231-
createGQLServiceWithTransactions(t, stack)
232-
}
233332
return stack
234333
}
235334

236-
func createGQLService(t *testing.T, stack *node.Node) {
237-
// create backend
238-
ethConf := &ethconfig.Config{
239-
Genesis: &core.Genesis{
240-
Config: params.AllEthashProtocolChanges,
241-
GasLimit: 11500000,
242-
Difficulty: big.NewInt(1048576),
243-
},
244-
Ethash: ethash.Config{
245-
PowMode: ethash.ModeFake,
246-
},
247-
NetworkId: 1337,
248-
TrieCleanCache: 5,
249-
TrieCleanCacheJournal: "triecache",
250-
TrieCleanCacheRejournal: 60 * time.Minute,
251-
TrieDirtyCache: 5,
252-
TrieTimeout: 60 * time.Minute,
253-
SnapshotCache: 5,
254-
}
255-
ethBackend, err := eth.New(stack, ethConf)
256-
if err != nil {
257-
t.Fatalf("could not create eth backend: %v", err)
258-
}
259-
// Create some blocks and import them
260-
chain, _ := core.GenerateChain(params.AllEthashProtocolChanges, ethBackend.BlockChain().Genesis(),
261-
ethash.NewFaker(), ethBackend.ChainDb(), 10, func(i int, gen *core.BlockGen) {})
262-
_, err = ethBackend.BlockChain().InsertChain(chain)
263-
if err != nil {
264-
t.Fatalf("could not create import blocks: %v", err)
265-
}
266-
// create gql service
267-
filterSystem := filters.NewFilterSystem(ethBackend.APIBackend, filters.Config{})
268-
err = New(stack, ethBackend.APIBackend, filterSystem, []string{}, []string{})
269-
if err != nil {
270-
t.Fatalf("could not create graphql service: %v", err)
271-
}
272-
}
273-
274-
func createGQLServiceWithTransactions(t *testing.T, stack *node.Node) {
275-
// create backend
276-
key, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
277-
address := crypto.PubkeyToAddress(key.PublicKey)
278-
funds := big.NewInt(1000000000000000)
279-
dad := common.HexToAddress("0x0000000000000000000000000000000000000dad")
280-
335+
func newGQLService(t *testing.T, stack *node.Node, gspec *core.Genesis, genBlocks int, genfunc func(i int, gen *core.BlockGen)) *handler {
281336
ethConf := &ethconfig.Config{
282-
Genesis: &core.Genesis{
283-
Config: params.AllEthashProtocolChanges,
284-
GasLimit: 11500000,
285-
Difficulty: big.NewInt(1048576),
286-
Alloc: core.GenesisAlloc{
287-
address: {Balance: funds},
288-
// The address 0xdad sloads 0x00 and 0x01
289-
dad: {
290-
Code: []byte{
291-
byte(vm.PC),
292-
byte(vm.PC),
293-
byte(vm.SLOAD),
294-
byte(vm.SLOAD),
295-
},
296-
Nonce: 0,
297-
Balance: big.NewInt(0),
298-
},
299-
},
300-
BaseFee: big.NewInt(params.InitialBaseFee),
301-
},
337+
Genesis: gspec,
302338
Ethash: ethash.Config{
303339
PowMode: ethash.ModeFake,
304340
},
@@ -310,49 +346,22 @@ func createGQLServiceWithTransactions(t *testing.T, stack *node.Node) {
310346
TrieTimeout: 60 * time.Minute,
311347
SnapshotCache: 5,
312348
}
313-
314349
ethBackend, err := eth.New(stack, ethConf)
315350
if err != nil {
316351
t.Fatalf("could not create eth backend: %v", err)
317352
}
318-
signer := types.LatestSigner(ethConf.Genesis.Config)
319-
320-
legacyTx, _ := types.SignNewTx(key, signer, &types.LegacyTx{
321-
Nonce: uint64(0),
322-
To: &dad,
323-
Value: big.NewInt(100),
324-
Gas: 50000,
325-
GasPrice: big.NewInt(params.InitialBaseFee),
326-
})
327-
envelopTx, _ := types.SignNewTx(key, signer, &types.AccessListTx{
328-
ChainID: ethConf.Genesis.Config.ChainID,
329-
Nonce: uint64(1),
330-
To: &dad,
331-
Gas: 30000,
332-
GasPrice: big.NewInt(params.InitialBaseFee),
333-
Value: big.NewInt(50),
334-
AccessList: types.AccessList{{
335-
Address: dad,
336-
StorageKeys: []common.Hash{{0}},
337-
}},
338-
})
339-
340353
// Create some blocks and import them
341354
chain, _ := core.GenerateChain(params.AllEthashProtocolChanges, ethBackend.BlockChain().Genesis(),
342-
ethash.NewFaker(), ethBackend.ChainDb(), 1, func(i int, b *core.BlockGen) {
343-
b.SetCoinbase(common.Address{1})
344-
b.AddTx(legacyTx)
345-
b.AddTx(envelopTx)
346-
})
347-
355+
ethash.NewFaker(), ethBackend.ChainDb(), genBlocks, genfunc)
348356
_, err = ethBackend.BlockChain().InsertChain(chain)
349357
if err != nil {
350358
t.Fatalf("could not create import blocks: %v", err)
351359
}
352-
// create gql service
360+
// Set up handler
353361
filterSystem := filters.NewFilterSystem(ethBackend.APIBackend, filters.Config{})
354-
err = New(stack, ethBackend.APIBackend, filterSystem, []string{}, []string{})
362+
handler, err := newHandler(stack, ethBackend.APIBackend, filterSystem, []string{}, []string{})
355363
if err != nil {
356364
t.Fatalf("could not create graphql service: %v", err)
357365
}
366+
return handler
358367
}

graphql/service.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,18 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
5757

5858
// New constructs a new GraphQL service instance.
5959
func New(stack *node.Node, backend ethapi.Backend, filterSystem *filters.FilterSystem, cors, vhosts []string) error {
60-
return newHandler(stack, backend, filterSystem, cors, vhosts)
60+
_, err := newHandler(stack, backend, filterSystem, cors, vhosts)
61+
return err
6162
}
6263

6364
// newHandler returns a new `http.Handler` that will answer GraphQL queries.
6465
// It additionally exports an interactive query browser on the / endpoint.
65-
func newHandler(stack *node.Node, backend ethapi.Backend, filterSystem *filters.FilterSystem, cors, vhosts []string) error {
66+
func newHandler(stack *node.Node, backend ethapi.Backend, filterSystem *filters.FilterSystem, cors, vhosts []string) (*handler, error) {
6667
q := Resolver{backend, filterSystem}
6768

6869
s, err := graphql.ParseSchema(schema, &q)
6970
if err != nil {
70-
return err
71+
return nil, err
7172
}
7273
h := handler{Schema: s}
7374
handler := node.NewHTTPHandlerStack(h, cors, vhosts, nil)
@@ -76,5 +77,5 @@ func newHandler(stack *node.Node, backend ethapi.Backend, filterSystem *filters.
7677
stack.RegisterHandler("GraphQL", "/graphql", handler)
7778
stack.RegisterHandler("GraphQL", "/graphql/", handler)
7879

79-
return nil
80+
return &h, nil
8081
}

0 commit comments

Comments
 (0)