Skip to content

Commit 55c15e9

Browse files
Merge branch 'stylus-master-896026b' into stylus-state-storage
2 parents c39800e + 2751178 commit 55c15e9

File tree

10 files changed

+161
-23
lines changed

10 files changed

+161
-23
lines changed

arbitrum/backend.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ func NewBackend(stack *node.Node, config *Config, chainDb ethdb.Database, publis
5555
if err != nil {
5656
return nil, nil, err
5757
}
58-
backend.shutdownTracker.MarkStartup()
5958
return backend, filterSystem, nil
6059
}
6160

@@ -86,6 +85,7 @@ func (b *Backend) ArbInterface() ArbInterface {
8685
// TODO: this is used when registering backend as lifecycle in stack
8786
func (b *Backend) Start() error {
8887
b.startBloomHandlers(b.config.BloomBitsBlocks)
88+
b.shutdownTracker.MarkStartup()
8989
b.shutdownTracker.Start()
9090

9191
return nil

arbitrum/recordingdb.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,10 @@ func (r *RecordingDatabase) GetOrRecreateState(ctx context.Context, header *type
289289
if currentHeader.Number.Uint64() <= genesis {
290290
return nil, fmt.Errorf("moved beyond genesis looking for state looking for %d, genesis %d, err %w", returnedBlockNumber, genesis, err)
291291
}
292+
lastHeader := currentHeader
292293
currentHeader = r.bc.GetHeader(currentHeader.ParentHash, currentHeader.Number.Uint64()-1)
293294
if currentHeader == nil {
294-
return nil, fmt.Errorf("chain doesn't contain parent of block %d hash %v", currentHeader.Number, currentHeader.Hash())
295+
return nil, fmt.Errorf("chain doesn't contain parent of block %d hash %v (expected parent hash %v)", lastHeader.Number, lastHeader.Hash(), lastHeader.ParentHash)
295296
}
296297
stateDb, err = r.StateFor(currentHeader)
297298
if err == nil {

core/state_processor.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import (
2626
"github.com/ethereum/go-ethereum/core/state"
2727
"github.com/ethereum/go-ethereum/core/types"
2828
"github.com/ethereum/go-ethereum/core/vm"
29-
"github.com/ethereum/go-ethereum/crypto"
3029
"github.com/ethereum/go-ethereum/params"
3130
)
3231

@@ -131,8 +130,8 @@ func applyTransaction(msg types.Message, config *params.ChainConfig, author *com
131130
receipt.GasUsed = result.UsedGas
132131

133132
// If the transaction created a contract, store the creation address in the receipt.
134-
if msg.To() == nil {
135-
receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
133+
if result.TopLevelDeployed != nil {
134+
receipt.ContractAddress = *result.TopLevelDeployed
136135
}
137136

138137
// Set the receipt logs and create the bloom filter.

core/state_transition.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ type ExecutionResult struct {
9292

9393
// Arbitrum: a tx may yield others that need to run afterward (see retryables)
9494
ScheduledTxes types.Transactions
95+
// Arbitrum: the contract deployed from the top-level transaction, or nil if not a contract creation tx
96+
TopLevelDeployed *common.Address
9597
}
9698

9799
// Unwrap returns the internal evm error which allows us for further
@@ -360,12 +362,14 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
360362
if rules.IsBerlin {
361363
st.state.PrepareAccessList(msg.From(), msg.To(), vm.ActivePrecompiles(rules), msg.AccessList())
362364
}
365+
var deployedContract *common.Address
363366
var (
364367
ret []byte
365368
vmerr error // vm errors do not effect consensus and are therefore not assigned to err
366369
)
367370
if contractCreation {
368-
ret, _, st.gas, vmerr = st.evm.Create(sender, st.data, st.gas, st.value)
371+
deployedContract = &common.Address{}
372+
ret, *deployedContract, st.gas, vmerr = st.evm.Create(sender, st.data, st.gas, st.value)
369373
} else {
370374
// Increment the nonce for the next transaction
371375
st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
@@ -410,10 +414,11 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
410414
}
411415

412416
return &ExecutionResult{
413-
UsedGas: st.gasUsed(),
414-
Err: vmerr,
415-
ReturnData: ret,
416-
ScheduledTxes: st.evm.ProcessingHook.ScheduledTxes(),
417+
UsedGas: st.gasUsed(),
418+
Err: vmerr,
419+
ReturnData: ret,
420+
ScheduledTxes: st.evm.ProcessingHook.ScheduledTxes(),
421+
TopLevelDeployed: deployedContract,
417422
}, nil
418423
}
419424

core/types/receipt.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ type storedReceiptRLP struct {
102102
CumulativeGasUsed uint64
103103
L1GasUsed uint64
104104
Logs []*LogForStorage
105+
ContractAddress *common.Address `rlp:"optional"` // set on new versions if an Arbitrum tx type
105106
}
106107

107108
type arbLegacyStoredReceiptRLP struct {
@@ -313,6 +314,9 @@ func (r *ReceiptForStorage) EncodeRLP(_w io.Writer) error {
313314
}
314315
}
315316
w.ListEnd(logList)
317+
if r.Type >= ArbitrumDepositTxType && r.Type != ArbitrumLegacyTxType && r.ContractAddress != (common.Address{}) {
318+
w.WriteBytes(r.ContractAddress[:])
319+
}
316320
w.ListEnd(outerList)
317321
return w.Flush()
318322
}
@@ -379,6 +383,9 @@ func decodeStoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
379383
r.Logs[i] = (*Log)(log)
380384
}
381385
r.Bloom = CreateBloom(Receipts{(*Receipt)(r)})
386+
if stored.ContractAddress != nil {
387+
r.ContractAddress = *stored.ContractAddress
388+
}
382389

383390
return nil
384391
}
@@ -464,7 +471,7 @@ func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, nu
464471

465472
if rs[i].Type != ArbitrumLegacyTxType {
466473
// The contract address can be derived from the transaction itself
467-
if txs[i].To() == nil {
474+
if txs[i].To() == nil && rs[i].ContractAddress == (common.Address{}) {
468475
// Deriving the signer is expensive, only do if it's actually needed
469476
from, _ := Sender(signer, txs[i])
470477
rs[i].ContractAddress = crypto.CreateAddress(from, txs[i].Nonce())

node/rpcstack_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package node
1818

1919
import (
2020
"bytes"
21+
"context"
2122
"fmt"
2223
"net/http"
2324
"net/url"
@@ -417,5 +418,21 @@ func TestJWT(t *testing.T) {
417418
t.Errorf("tc %d-http, token '%v': expected not to allow, got %v", i, token, resp.StatusCode)
418419
}
419420
}
421+
ctx, cancel := context.WithCancel(context.Background())
422+
defer cancel()
423+
client, err := rpc.DialWebsocketJWT(ctx, wsUrl, "orig", []byte("secret"))
424+
if err != nil {
425+
t.Errorf("DialWebsocketJWT should have succeeded, got %v", err)
426+
}
427+
if client != nil {
428+
client.Close()
429+
}
430+
client, err = rpc.DialWebsocketJWT(ctx, wsUrl, "orig", []byte("bad"))
431+
if err == nil {
432+
t.Error("DialWebsocketJWT with bad secret should have failed")
433+
}
434+
if client != nil {
435+
client.Close()
436+
}
420437
srv.stop()
421438
}

rpc/client.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ type BatchElem struct {
7474

7575
// Client represents a connection to an RPC server.
7676
type Client struct {
77+
requestHook RequestHook
78+
7779
idgen func() ID // for subscriptions
7880
isHTTP bool // connection type: http, ws or ipc
7981
services *serviceRegistry
@@ -300,25 +302,32 @@ func (c *Client) CallContext(ctx context.Context, result interface{}, method str
300302
}
301303
op := &requestOp{ids: []json.RawMessage{msg.ID}, resp: make(chan *jsonrpcMessage, 1)}
302304

305+
resultHook := c.onRequest(msg)
303306
if c.isHTTP {
304307
err = c.sendHTTP(ctx, op, msg)
305308
} else {
306309
err = c.send(ctx, op, msg)
307310
}
308311
if err != nil {
312+
resultHook.OnResult(nil, err)
309313
return err
310314
}
311315

312316
// dispatch has accepted the request and will close the channel when it quits.
313317
switch resp, err := op.wait(ctx, c); {
314318
case err != nil:
319+
resultHook.OnResult(resp, err)
315320
return err
316321
case resp.Error != nil:
322+
resultHook.OnResult(resp, resp.Error)
317323
return resp.Error
318324
case len(resp.Result) == 0:
325+
resultHook.OnResult(resp, ErrNoResult)
319326
return ErrNoResult
320327
default:
321-
return json.Unmarshal(resp.Result, &result)
328+
err := json.Unmarshal(resp.Result, &result)
329+
resultHook.OnResult(resp, err)
330+
return err
322331
}
323332
}
324333

@@ -362,6 +371,12 @@ func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error {
362371
byID[string(msg.ID)] = i
363372
}
364373

374+
resultHooks := make([]ResultHook, len(msgs))
375+
responsesForHooks := make([]interface{}, len(msgs))
376+
for i, msg := range msgs {
377+
resultHooks[i] = c.onRequest(msg)
378+
}
379+
365380
var err error
366381
if c.isHTTP {
367382
err = c.sendBatchHTTP(ctx, op, msgs)
@@ -379,7 +394,9 @@ func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error {
379394
// Find the element corresponding to this response.
380395
// The element is guaranteed to be present because dispatch
381396
// only sends valid IDs to our channel.
382-
elem := &b[byID[string(resp.ID)]]
397+
idx := byID[string(resp.ID)]
398+
responsesForHooks[idx] = resp
399+
elem := &b[idx]
383400
if resp.Error != nil {
384401
elem.Error = resp.Error
385402
continue
@@ -390,6 +407,9 @@ func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error {
390407
}
391408
elem.Error = json.Unmarshal(resp.Result, elem.Result)
392409
}
410+
for i, hook := range resultHooks {
411+
hook.OnResult(responsesForHooks[i], err)
412+
}
393413
return err
394414
}
395415

rpc/client_arbitrum.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
// Copyright 2022 The go-ethereum Authors
2+
// This file is part of the go-ethereum library.
3+
//
4+
// The go-ethereum library is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// The go-ethereum library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16+
117
package rpc
218

319
import (
@@ -34,3 +50,37 @@ func DialTransport(ctx context.Context, rawUrl string, transport *http.Transport
3450
}
3551
return rpcClient, nil
3652
}
53+
54+
func DialContextWithRequestHook(ctx context.Context, url string, hook RequestHook) (*Client, error) {
55+
client, err := DialContext(ctx, url)
56+
if err != nil {
57+
return nil, err
58+
}
59+
client.requestHook = hook
60+
return client, nil
61+
}
62+
63+
type RequestHook interface {
64+
OnRequest(request interface{}) ResultHook
65+
}
66+
67+
type ResultHook interface {
68+
OnResult(response interface{}, err error)
69+
}
70+
71+
type noopResultHook struct{}
72+
73+
func (h noopResultHook) OnResult(interface{}, error) {
74+
}
75+
76+
func (c *Client) onRequest(request interface{}) ResultHook {
77+
hooks := c.requestHook
78+
var respHooks ResultHook
79+
if hooks != nil {
80+
respHooks = hooks.OnRequest(request)
81+
}
82+
if respHooks == nil {
83+
respHooks = noopResultHook{}
84+
}
85+
return respHooks
86+
}

rpc/handler.go

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package rpc
1919
import (
2020
"context"
2121
"encoding/json"
22+
"fmt"
2223
"reflect"
2324
"strconv"
2425
"strings"
@@ -34,21 +35,20 @@ import (
3435
//
3536
// The entry points for incoming messages are:
3637
//
37-
// h.handleMsg(message)
38-
// h.handleBatch(message)
38+
// h.handleMsg(message)
39+
// h.handleBatch(message)
3940
//
4041
// Outgoing calls use the requestOp struct. Register the request before sending it
4142
// on the connection:
4243
//
43-
// op := &requestOp{ids: ...}
44-
// h.addRequestOp(op)
44+
// op := &requestOp{ids: ...}
45+
// h.addRequestOp(op)
4546
//
4647
// Now send the request, then wait for the reply to be delivered through handleMsg:
4748
//
48-
// if err := op.wait(...); err != nil {
49-
// h.removeRequestOp(op) // timeout, etc.
50-
// }
51-
//
49+
// if err := op.wait(...); err != nil {
50+
// h.removeRequestOp(op) // timeout, etc.
51+
// }
5252
type handler struct {
5353
reg *serviceRegistry
5454
unsubscribeCb *callback
@@ -92,6 +92,8 @@ func newHandler(connCtx context.Context, conn jsonWriter, idgen func() ID, reg *
9292
return h
9393
}
9494

95+
const maxBatchResponseSize int = 10_000_000 // 10MB
96+
9597
// handleBatch executes all messages in a batch and returns the responses.
9698
func (h *handler) handleBatch(msgs []*jsonrpcMessage) {
9799
// Emit error response for empty batches:
@@ -114,10 +116,21 @@ func (h *handler) handleBatch(msgs []*jsonrpcMessage) {
114116
}
115117
// Process calls on a goroutine because they may block indefinitely:
116118
h.startCallProc(func(cp *callProc) {
117-
answers := make([]*jsonrpcMessage, 0, len(msgs))
119+
answers := make([]json.RawMessage, 0, len(msgs))
120+
var totalSize int
118121
for _, msg := range calls {
119122
if answer := h.handleCallMsg(cp, msg); answer != nil {
120-
answers = append(answers, answer)
123+
serialized, err := json.Marshal(answer)
124+
if err != nil {
125+
h.conn.writeJSON(cp.ctx, errorMessage(&parseError{"error serializing response: " + err.Error()}))
126+
return
127+
}
128+
totalSize += len(serialized)
129+
if totalSize > maxBatchResponseSize {
130+
h.conn.writeJSON(cp.ctx, errorMessage(&invalidRequestError{fmt.Sprintf("batch response exceeded limit of %v bytes", maxBatchResponseSize)}))
131+
return
132+
}
133+
answers = append(answers, serialized)
121134
}
122135
}
123136
h.addSubscriptions(cp.notifiers)

0 commit comments

Comments
 (0)