Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
cc02fdf7
Unverified
Commit
cc02fdf7
authored
Nov 29, 2021
by
Mark Tyneway
Committed by
GitHub
Nov 29, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1720 from ethereum-optimism/feat/allow-unprotected-txs
l2geth: allow for unprotected txs
parents
4c35ece9
6bd6768e
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
141 additions
and
29 deletions
+141
-29
nice-steaks-hammer.md
.changeset/nice-steaks-hammer.md
+5
-0
old-moons-invite.md
.changeset/old-moons-invite.md
+6
-0
integration.yml
.github/workflows/integration.yml
+1
-1
package.json
integration-tests/package.json
+1
-0
replica.spec.ts
integration-tests/test/replica.spec.ts
+75
-0
rpc.spec.ts
integration-tests/test/rpc.spec.ts
+7
-4
env.ts
integration-tests/test/shared/env.ts
+4
-0
utils.ts
integration-tests/test/shared/utils.ts
+9
-3
api.go
l2geth/internal/ethapi/api.go
+0
-3
client.go
l2geth/rollup/client.go
+20
-13
docker-compose.yml
ops/docker-compose.yml
+5
-3
eth-tx.ts
packages/data-transport-layer/src/utils/eth-tx.ts
+8
-2
No files found.
.changeset/nice-steaks-hammer.md
0 → 100644
View file @
cc02fdf7
---
'
@eth-optimism/data-transport-layer'
:
patch
---
Handle unprotected transactions
.changeset/old-moons-invite.md
0 → 100644
View file @
cc02fdf7
---
'
@eth-optimism/integration-tests'
:
patch
'
@eth-optimism/l2geth'
:
patch
---
Allow for unprotected transactions
.github/workflows/integration.yml
View file @
cc02fdf7
...
...
@@ -55,7 +55,7 @@ jobs:
if
:
failure()
uses
:
jwalton/gh-docker-logs@v1
with
:
images
:
'
ethereumoptimism/hardhat,ops_deployer,ops_dtl,
ethereumoptimism/l2geth,ethereumoptimism/message-relayer,ops_batch_submitter,ethereumoptimism/l2geth
,ops_integration_tests'
images
:
'
ethereumoptimism/hardhat,ops_deployer,ops_dtl,
ops_l2geth,ethereumoptimism/message-relayer,ops_batch_submitter,ops_replica
,ops_integration_tests'
dest
:
'
/home/runner/logs'
-
name
:
Tar logs
...
...
integration-tests/package.json
View file @
cc02fdf7
...
...
@@ -31,6 +31,7 @@
"@eth-optimism/contracts"
:
"0.5.4"
,
"@eth-optimism/core-utils"
:
"0.7.2"
,
"@eth-optimism/message-relayer"
:
"0.2.4"
,
"@ethersproject/abstract-provider"
:
"^5.5.1"
,
"@ethersproject/providers"
:
"^5.4.5"
,
"@ethersproject/transactions"
:
"^5.4.0"
,
"@nomiclabs/hardhat-ethers"
:
"^2.0.2"
,
...
...
integration-tests/test/replica.spec.ts
0 → 100644
View file @
cc02fdf7
import
{
OptimismEnv
}
from
'
./shared/env
'
import
{
defaultTransactionFactory
,
gasPriceForL2
,
sleep
,
isLiveNetwork
,
}
from
'
./shared/utils
'
import
{
expect
}
from
'
chai
'
import
{
TransactionReceipt
}
from
'
@ethersproject/abstract-provider
'
describe
(
'
Replica Tests
'
,
()
=>
{
let
env
:
OptimismEnv
before
(
async
()
=>
{
env
=
await
OptimismEnv
.
new
()
})
describe
(
'
Matching blocks
'
,
()
=>
{
if
(
isLiveNetwork
())
{
console
.
log
(
'
Skipping replica tests on live network
'
)
return
}
it
(
'
should sync a transaction
'
,
async
()
=>
{
const
tx
=
defaultTransactionFactory
()
tx
.
gasPrice
=
await
gasPriceForL2
(
env
)
const
result
=
await
env
.
l2Wallet
.
sendTransaction
(
tx
)
let
receipt
:
TransactionReceipt
while
(
!
receipt
)
{
receipt
=
await
env
.
replicaProvider
.
getTransactionReceipt
(
result
.
hash
)
await
sleep
(
200
)
}
const
sequencerBlock
=
(
await
env
.
l2Provider
.
getBlock
(
result
.
blockNumber
))
as
any
const
replicaBlock
=
(
await
env
.
replicaProvider
.
getBlock
(
result
.
blockNumber
))
as
any
expect
(
sequencerBlock
.
stateRoot
).
to
.
deep
.
eq
(
replicaBlock
.
stateRoot
)
expect
(
sequencerBlock
.
hash
).
to
.
deep
.
eq
(
replicaBlock
.
hash
)
})
it
(
'
sync an unprotected tx (eip155)
'
,
async
()
=>
{
const
tx
=
{
...
defaultTransactionFactory
(),
nonce
:
await
env
.
l2Wallet
.
getTransactionCount
(),
gasPrice
:
await
gasPriceForL2
(
env
),
chainId
:
null
,
// Disables EIP155 transaction signing.
}
const
signed
=
await
env
.
l2Wallet
.
signTransaction
(
tx
)
const
result
=
await
env
.
l2Provider
.
sendTransaction
(
signed
)
let
receipt
:
TransactionReceipt
while
(
!
receipt
)
{
receipt
=
await
env
.
replicaProvider
.
getTransactionReceipt
(
result
.
hash
)
await
sleep
(
200
)
}
const
sequencerBlock
=
(
await
env
.
l2Provider
.
getBlock
(
result
.
blockNumber
))
as
any
const
replicaBlock
=
(
await
env
.
replicaProvider
.
getBlock
(
result
.
blockNumber
))
as
any
expect
(
sequencerBlock
.
stateRoot
).
to
.
deep
.
eq
(
replicaBlock
.
stateRoot
)
expect
(
sequencerBlock
.
hash
).
to
.
deep
.
eq
(
replicaBlock
.
hash
)
})
})
})
integration-tests/test/rpc.spec.ts
View file @
cc02fdf7
...
...
@@ -84,16 +84,19 @@ describe('Basic RPC tests', () => {
).
to
.
be
.
rejectedWith
(
'
invalid transaction: invalid sender
'
)
})
it
(
'
should
not
accept a transaction without a chain ID
'
,
async
()
=>
{
it
(
'
should accept a transaction without a chain ID
'
,
async
()
=>
{
const
tx
=
{
...
defaultTransactionFactory
(),
nonce
:
await
wallet
.
getTransactionCount
(),
gasPrice
:
await
gasPriceForL2
(
env
),
chainId
:
null
,
// Disables EIP155 transaction signing.
}
const
signed
=
await
wallet
.
signTransaction
(
tx
)
const
response
=
await
provider
.
sendTransaction
(
signed
)
await
expect
(
provider
.
sendTransaction
(
await
wallet
.
signTransaction
(
tx
))
).
to
.
be
.
rejectedWith
(
'
Cannot submit unprotected transaction
'
)
expect
(
response
.
chainId
).
to
.
equal
(
0
)
const
v
=
response
.
v
expect
(
v
===
27
||
v
===
28
).
to
.
be
.
true
})
it
(
'
should accept a transaction with a value
'
,
async
()
=>
{
...
...
integration-tests/test/shared/env.ts
View file @
cc02fdf7
...
...
@@ -10,6 +10,7 @@ import {
getAddressManager
,
l1Provider
,
l2Provider
,
replicaProvider
,
l1Wallet
,
l2Wallet
,
fundUser
,
...
...
@@ -52,6 +53,7 @@ export class OptimismEnv {
// The providers
l1Provider
:
providers
.
JsonRpcProvider
l2Provider
:
providers
.
JsonRpcProvider
replicaProvider
:
providers
.
JsonRpcProvider
constructor
(
args
:
any
)
{
this
.
addressManager
=
args
.
addressManager
...
...
@@ -67,6 +69,7 @@ export class OptimismEnv {
this
.
l2Wallet
=
args
.
l2Wallet
this
.
l1Provider
=
args
.
l1Provider
this
.
l2Provider
=
args
.
l2Provider
this
.
replicaProvider
=
args
.
replicaProvider
this
.
ctc
=
args
.
ctc
this
.
scc
=
args
.
scc
}
...
...
@@ -126,6 +129,7 @@ export class OptimismEnv {
l2Wallet
,
l1Provider
,
l2Provider
,
replicaProvider
,
})
}
...
...
integration-tests/test/shared/utils.ts
View file @
cc02fdf7
...
...
@@ -55,13 +55,19 @@ const env = cleanEnv(process.env, {
export
const
l1Provider
=
new
providers
.
JsonRpcProvider
(
env
.
L1_URL
)
l1Provider
.
pollingInterval
=
env
.
L1_POLLING_INTERVAL
export
const
l2Provider
=
new
providers
.
JsonRpcProvider
(
env
.
L2_URL
)
export
const
l2Provider
=
injectL2Context
(
new
providers
.
JsonRpcProvider
(
env
.
L2_URL
)
)
l2Provider
.
pollingInterval
=
env
.
L2_POLLING_INTERVAL
export
const
verifierProvider
=
new
providers
.
JsonRpcProvider
(
env
.
VERIFIER_URL
)
export
const
verifierProvider
=
injectL2Context
(
new
providers
.
JsonRpcProvider
(
env
.
VERIFIER_URL
)
)
verifierProvider
.
pollingInterval
=
env
.
VERIFIER_POLLING_INTERVAL
export
const
replicaProvider
=
new
providers
.
JsonRpcProvider
(
env
.
REPLICA_URL
)
export
const
replicaProvider
=
injectL2Context
(
new
providers
.
JsonRpcProvider
(
env
.
REPLICA_URL
)
)
replicaProvider
.
pollingInterval
=
env
.
REPLICA_POLLING_INTERVAL
// The sequencer private key which is funded on L1
...
...
l2geth/internal/ethapi/api.go
View file @
cc02fdf7
...
...
@@ -1573,9 +1573,6 @@ func (args *SendTxArgs) toTransaction() *types.Transaction {
// SubmitTransaction is a helper function that submits tx to txPool and logs a message.
func
SubmitTransaction
(
ctx
context
.
Context
,
b
Backend
,
tx
*
types
.
Transaction
)
(
common
.
Hash
,
error
)
{
if
!
tx
.
Protected
()
{
return
common
.
Hash
{},
errors
.
New
(
"Cannot submit unprotected transaction"
)
}
if
err
:=
b
.
SendTx
(
ctx
,
tx
);
err
!=
nil
{
return
common
.
Hash
{},
err
}
...
...
l2geth/rollup/client.go
View file @
cc02fdf7
...
...
@@ -134,8 +134,8 @@ type RollupClient interface {
// Client is an HTTP based RollupClient
type
Client
struct
{
client
*
resty
.
Client
signer
*
types
.
EIP155Signer
client
*
resty
.
Client
chainID
*
big
.
Int
}
// TransactionResponse represents the response from the remote server when
...
...
@@ -166,11 +166,10 @@ func NewClient(url string, chainID *big.Int) *Client {
}
return
nil
})
signer
:=
types
.
NewEIP155Signer
(
chainID
)
return
&
Client
{
client
:
client
,
signer
:
&
signer
,
client
:
client
,
chainID
:
chainID
,
}
}
...
...
@@ -322,7 +321,7 @@ func (c *Client) GetLatestTransactionBatchIndex() (*uint64, error) {
// batchedTransactionToTransaction converts a transaction into a
// types.Transaction that can be consumed by the SyncService
func
batchedTransactionToTransaction
(
res
*
transaction
,
signer
*
types
.
EIP155Signer
)
(
*
types
.
Transaction
,
error
)
{
func
batchedTransactionToTransaction
(
res
*
transaction
,
chainID
*
big
.
Int
)
(
*
types
.
Transaction
,
error
)
{
// `nil` transactions are not found
if
res
==
nil
{
return
nil
,
errElementNotFound
...
...
@@ -373,7 +372,15 @@ func batchedTransactionToTransaction(res *transaction, signer *types.EIP155Signe
sig
:=
make
([]
byte
,
crypto
.
SignatureLength
)
copy
(
sig
[
32
-
len
(
r
)
:
32
],
r
)
copy
(
sig
[
64
-
len
(
s
)
:
64
],
s
)
sig
[
64
]
=
byte
(
res
.
Decoded
.
Signature
.
V
)
var
signer
types
.
Signer
if
res
.
Decoded
.
Signature
.
V
==
27
||
res
.
Decoded
.
Signature
.
V
==
28
{
signer
=
types
.
HomesteadSigner
{}
sig
[
64
]
=
byte
(
res
.
Decoded
.
Signature
.
V
-
27
)
}
else
{
signer
=
types
.
NewEIP155Signer
(
chainID
)
sig
[
64
]
=
byte
(
res
.
Decoded
.
Signature
.
V
)
}
tx
,
err
:=
tx
.
WithSignature
(
signer
,
sig
[
:
])
if
err
!=
nil
{
...
...
@@ -431,7 +438,7 @@ func (c *Client) GetTransaction(index uint64, backend Backend) (*types.Transacti
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"could not get tx with index %d"
,
index
)
}
return
batchedTransactionToTransaction
(
res
.
Transaction
,
c
.
signer
)
return
batchedTransactionToTransaction
(
res
.
Transaction
,
c
.
chainID
)
}
// GetLatestTransaction will get the latest transaction, meaning the transaction
...
...
@@ -452,7 +459,7 @@ func (c *Client) GetLatestTransaction(backend Backend) (*types.Transaction, erro
return
nil
,
errors
.
New
(
"Cannot get latest transaction"
)
}
return
batchedTransactionToTransaction
(
res
.
Transaction
,
c
.
signer
)
return
batchedTransactionToTransaction
(
res
.
Transaction
,
c
.
chainID
)
}
// GetEthContext will return the EthContext by block number
...
...
@@ -564,7 +571,7 @@ func (c *Client) GetLatestTransactionBatch() (*Batch, []*types.Transaction, erro
if
!
ok
{
return
nil
,
nil
,
fmt
.
Errorf
(
"Cannot parse transaction batch response"
)
}
return
parseTransactionBatchResponse
(
txBatch
,
c
.
signer
)
return
parseTransactionBatchResponse
(
txBatch
,
c
.
chainID
)
}
// GetTransactionBatch will return the transaction batch by batch index
...
...
@@ -584,19 +591,19 @@ func (c *Client) GetTransactionBatch(index uint64) (*Batch, []*types.Transaction
if
!
ok
{
return
nil
,
nil
,
fmt
.
Errorf
(
"Cannot parse transaction batch response"
)
}
return
parseTransactionBatchResponse
(
txBatch
,
c
.
signer
)
return
parseTransactionBatchResponse
(
txBatch
,
c
.
chainID
)
}
// parseTransactionBatchResponse will turn a TransactionBatchResponse into a
// Batch and its corresponding types.Transactions
func
parseTransactionBatchResponse
(
txBatch
*
TransactionBatchResponse
,
signer
*
types
.
EIP155Signer
)
(
*
Batch
,
[]
*
types
.
Transaction
,
error
)
{
func
parseTransactionBatchResponse
(
txBatch
*
TransactionBatchResponse
,
chainID
*
big
.
Int
)
(
*
Batch
,
[]
*
types
.
Transaction
,
error
)
{
if
txBatch
==
nil
||
txBatch
.
Batch
==
nil
{
return
nil
,
nil
,
errElementNotFound
}
batch
:=
txBatch
.
Batch
txs
:=
make
([]
*
types
.
Transaction
,
len
(
txBatch
.
Transactions
))
for
i
,
tx
:=
range
txBatch
.
Transactions
{
transaction
,
err
:=
batchedTransactionToTransaction
(
tx
,
signer
)
transaction
,
err
:=
batchedTransactionToTransaction
(
tx
,
chainID
)
if
err
!=
nil
{
return
nil
,
nil
,
fmt
.
Errorf
(
"Cannot parse transaction batch: %w"
,
err
)
}
...
...
ops/docker-compose.yml
View file @
cc02fdf7
...
...
@@ -165,7 +165,7 @@ services:
depends_on
:
-
dtl
deploy
:
replicas
:
0
replicas
:
1
build
:
context
:
..
dockerfile
:
./ops/docker/Dockerfile.geth
...
...
@@ -181,8 +181,8 @@ services:
ETH1_CTC_DEPLOYMENT_HEIGHT
:
8
RETRIES
:
60
ports
:
-
${
L2GETH
_HTTP_PORT:-8549}:8545
-
${
L2GETH
_WS_PORT:-8550}:8546
-
${
REPLICA
_HTTP_PORT:-8549}:8545
-
${
REPLICA
_WS_PORT:-8550}:8546
integration_tests
:
deploy
:
...
...
@@ -195,6 +195,8 @@ services:
environment
:
L1_URL
:
http://l1_chain:8545
L2_URL
:
http://l2geth:8545
REPLICA_URL
:
http://replica:8545
VERIFIER_URL
:
http://verifier:8545
URL
:
http://deployer:8081/addresses.json
ENABLE_GAS_REPORT
:
1
NO_NETWORK
:
1
...
...
packages/data-transport-layer/src/utils/eth-tx.ts
View file @
cc02fdf7
...
...
@@ -2,8 +2,14 @@
import
{
ethers
}
from
'
ethers
'
export
const
parseSignatureVParam
=
(
v
:
number
|
ethers
.
BigNumber
,
v
:
number
|
ethers
.
BigNumber
|
string
,
chainId
:
number
):
number
=>
{
return
ethers
.
BigNumber
.
from
(
v
).
toNumber
()
-
2
*
chainId
-
35
v
=
ethers
.
BigNumber
.
from
(
v
).
toNumber
()
// Handle unprotected transactions
if
(
v
===
27
||
v
===
28
)
{
return
v
}
// Handle EIP155 transactions
return
v
-
2
*
chainId
-
35
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment