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
8d98d5d4
Unverified
Commit
8d98d5d4
authored
Feb 06, 2023
by
mergify[bot]
Committed by
GitHub
Feb 06, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into seb/batcher-watch-timeouts
parents
e03b5073
407f97b9
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
320 additions
and
14 deletions
+320
-14
quick-crabs-argue.md
.changeset/quick-crabs-argue.md
+5
-0
wet-files-knock.md
.changeset/wet-files-knock.md
+5
-0
attributes_queue.go
op-node/rollup/derive/attributes_queue.go
+1
-1
engine_queue.go
op-node/rollup/derive/engine_queue.go
+1
-1
.env.example
packages/chain-mon/.env.example
+11
-0
package.json
packages/chain-mon/package.json
+5
-1
index.ts
packages/chain-mon/src/index.ts
+1
-0
service.ts
packages/chain-mon/src/wd-mon/service.ts
+232
-0
.eslintrc.js
packages/sdk/.eslintrc.js
+43
-0
l2-provider.ts
packages/sdk/src/l2-provider.ts
+1
-2
assert.ts
packages/sdk/src/utils/assert.ts
+5
-0
coercion.ts
packages/sdk/src/utils/coercion.ts
+1
-2
bridges.md
specs/bridges.md
+0
-1
derivation.md
specs/derivation.md
+3
-0
withdrawals.md
specs/withdrawals.md
+3
-3
yarn.lock
yarn.lock
+3
-3
No files found.
.changeset/quick-crabs-argue.md
0 → 100644
View file @
8d98d5d4
---
'
@eth-optimism/sdk'
:
patch
---
Remove assert node builtin from sdk
.changeset/wet-files-knock.md
0 → 100644
View file @
8d98d5d4
---
'
@eth-optimism/chain-mon'
:
patch
---
Added withdrawal monitoring to identify proven withdrawals not included in the L2ToL1MessagePasser's sentMessages mapping
op-node/rollup/derive/attributes_queue.go
View file @
8d98d5d4
...
@@ -20,7 +20,7 @@ import (
...
@@ -20,7 +20,7 @@ import (
// It also buffers batches that have been output because multiple batches can
// It also buffers batches that have been output because multiple batches can
// be created at once.
// be created at once.
//
//
// This stage can be reset by clearing it
'
s batch buffer.
// This stage can be reset by clearing its batch buffer.
// This stage does not need to retain any references to L1 blocks.
// This stage does not need to retain any references to L1 blocks.
type
AttributesBuilder
interface
{
type
AttributesBuilder
interface
{
...
...
op-node/rollup/derive/engine_queue.go
View file @
8d98d5d4
...
@@ -517,7 +517,7 @@ func (eq *EngineQueue) ConfirmPayload(ctx context.Context) (out *eth.ExecutionPa
...
@@ -517,7 +517,7 @@ func (eq *EngineQueue) ConfirmPayload(ctx context.Context) (out *eth.ExecutionPa
return
nil
,
BlockInsertPrestateErr
,
fmt
.
Errorf
(
"cannot complete payload building: not currently building a payload"
)
return
nil
,
BlockInsertPrestateErr
,
fmt
.
Errorf
(
"cannot complete payload building: not currently building a payload"
)
}
}
if
eq
.
buildingOnto
.
Hash
!=
eq
.
unsafeHead
.
Hash
{
// E.g. when safe-attributes consolidation fails, it will drop the existing work.
if
eq
.
buildingOnto
.
Hash
!=
eq
.
unsafeHead
.
Hash
{
// E.g. when safe-attributes consolidation fails, it will drop the existing work.
eq
.
log
.
Warn
(
"engine is building block that reorgs previous usafe head"
,
"onto"
,
eq
.
buildingOnto
,
"unsafe"
,
eq
.
unsafeHead
)
eq
.
log
.
Warn
(
"engine is building block that reorgs previous u
n
safe head"
,
"onto"
,
eq
.
buildingOnto
,
"unsafe"
,
eq
.
unsafeHead
)
}
}
fc
:=
eth
.
ForkchoiceState
{
fc
:=
eth
.
ForkchoiceState
{
HeadBlockHash
:
common
.
Hash
{},
// gets overridden
HeadBlockHash
:
common
.
Hash
{},
// gets overridden
...
...
packages/chain-mon/.env.example
View file @
8d98d5d4
...
@@ -7,3 +7,14 @@ DRIPPIE_MON__RPC=
...
@@ -7,3 +7,14 @@ DRIPPIE_MON__RPC=
# Address of the Drippie contract
# Address of the Drippie contract
DRIPPIE_MON__DRIPPIE_ADDRESS=
DRIPPIE_MON__DRIPPIE_ADDRESS=
###############################################################################
# ↓ wd-mon ↓ #
###############################################################################
# RPCs pointing to a base chain and ptimism chain
TWO_STEP_MONITOR__L1_RPC_PROVIDER=
TWO_STEP_MONITOR__L2_RPC_PROVIDER=
# The block number to start monitoring from
TWO_STEP_MONITOR__START_BLOCK_NUMBER=
packages/chain-mon/package.json
View file @
8d98d5d4
...
@@ -10,6 +10,7 @@
...
@@ -10,6 +10,7 @@
],
],
"scripts"
:
{
"scripts"
:
{
"start:drippie-mon"
:
"ts-node ./src/drippie-mon/service.ts"
,
"start:drippie-mon"
:
"ts-node ./src/drippie-mon/service.ts"
,
"start:wd-mon"
:
"ts-node ./src/wd-mon/service.ts"
,
"test:coverage"
:
"echo 'No tests defined.'"
,
"test:coverage"
:
"echo 'No tests defined.'"
,
"build"
:
"tsc -p ./tsconfig.json"
,
"build"
:
"tsc -p ./tsconfig.json"
,
"clean"
:
"rimraf dist/ ./tsconfig.tsbuildinfo"
,
"clean"
:
"rimraf dist/ ./tsconfig.tsbuildinfo"
,
...
@@ -35,7 +36,10 @@
...
@@ -35,7 +36,10 @@
"@eth-optimism/contracts-periphery"
:
"1.0.7"
,
"@eth-optimism/contracts-periphery"
:
"1.0.7"
,
"@eth-optimism/core-utils"
:
"0.12.0"
,
"@eth-optimism/core-utils"
:
"0.12.0"
,
"@eth-optimism/sdk"
:
"1.10.1"
,
"@eth-optimism/sdk"
:
"1.10.1"
,
"ethers"
:
"^5.7.0"
"ethers"
:
"^5.7.0"
,
"@types/dateformat"
:
"^5.0.0"
,
"chai-as-promised"
:
"^7.1.1"
,
"dateformat"
:
"^4.5.1"
},
},
"devDependencies"
:
{
"devDependencies"
:
{
"@ethersproject/abstract-provider"
:
"^5.7.0"
,
"@ethersproject/abstract-provider"
:
"^5.7.0"
,
...
...
packages/chain-mon/src/index.ts
View file @
8d98d5d4
export
*
from
'
./drippie-mon/service
'
export
*
from
'
./drippie-mon/service
'
export
*
from
'
./wd-mon/service
'
packages/chain-mon/src/wd-mon/service.ts
0 → 100644
View file @
8d98d5d4
import
{
BaseServiceV2
,
StandardOptions
,
ExpressRouter
,
Gauge
,
validators
,
waitForProvider
,
}
from
'
@eth-optimism/common-ts
'
import
{
CrossChainMessenger
}
from
'
@eth-optimism/sdk
'
import
{
getChainId
,
sleep
}
from
'
@eth-optimism/core-utils
'
import
{
Provider
}
from
'
@ethersproject/abstract-provider
'
import
{
Event
}
from
'
ethers
'
import
dateformat
from
'
dateformat
'
import
{
version
}
from
'
../../package.json
'
type
Options
=
{
l1RpcProvider
:
Provider
l2RpcProvider
:
Provider
startBlockNumber
:
number
sleepTimeMs
:
number
}
type
Metrics
=
{
withdrawalsValidated
:
Gauge
isDetectingForgeries
:
Gauge
nodeConnectionFailures
:
Gauge
}
type
State
=
{
messenger
:
CrossChainMessenger
highestUncheckedBlockNumber
:
number
finalizationWindow
:
number
forgeryDetected
:
boolean
}
export
class
WithdrawalMonitor
extends
BaseServiceV2
<
Options
,
Metrics
,
State
>
{
constructor
(
options
?:
Partial
<
Options
&
StandardOptions
>
)
{
super
({
version
,
name
:
'
two-step-monitor
'
,
loop
:
true
,
options
:
{
loopIntervalMs
:
1000
,
...
options
,
},
optionsSpec
:
{
l1RpcProvider
:
{
validator
:
validators
.
provider
,
desc
:
'
Provider for interacting with L1
'
,
},
l2RpcProvider
:
{
validator
:
validators
.
provider
,
desc
:
'
Provider for interacting with L2
'
,
},
startBlockNumber
:
{
validator
:
validators
.
num
,
default
:
-
1
,
desc
:
'
L1 block number to start checking from
'
,
public
:
true
,
},
sleepTimeMs
:
{
validator
:
validators
.
num
,
default
:
15000
,
desc
:
'
Time in ms to sleep when waiting for a node
'
,
public
:
true
,
},
},
metricsSpec
:
{
withdrawalsValidated
:
{
type
:
Gauge
,
desc
:
'
Latest L1 Block (checked and known)
'
,
labels
:
[
'
type
'
],
},
isDetectingForgeries
:
{
type
:
Gauge
,
desc
:
'
0 if state is ok. 1 or more if forged withdrawals are detected.
'
,
},
nodeConnectionFailures
:
{
type
:
Gauge
,
desc
:
'
Number of times node connection has failed
'
,
labels
:
[
'
layer
'
,
'
section
'
],
},
},
})
}
async
init
():
Promise
<
void
>
{
// Connect to L1.
await
waitForProvider
(
this
.
options
.
l1RpcProvider
,
{
logger
:
this
.
logger
,
name
:
'
L1
'
,
})
// Connect to L2.
await
waitForProvider
(
this
.
options
.
l2RpcProvider
,
{
logger
:
this
.
logger
,
name
:
'
L2
'
,
})
this
.
state
.
messenger
=
new
CrossChainMessenger
({
l1SignerOrProvider
:
this
.
options
.
l1RpcProvider
,
l2SignerOrProvider
:
this
.
options
.
l2RpcProvider
,
l1ChainId
:
await
getChainId
(
this
.
options
.
l1RpcProvider
),
l2ChainId
:
await
getChainId
(
this
.
options
.
l2RpcProvider
),
})
// Not detected by default.
this
.
state
.
forgeryDetected
=
false
// For now we'll just start take it from the env or the tip of the chain
if
(
this
.
options
.
startBlockNumber
===
-
1
)
{
this
.
state
.
highestUncheckedBlockNumber
=
await
this
.
options
.
l1RpcProvider
.
getBlockNumber
()
}
else
{
this
.
state
.
highestUncheckedBlockNumber
=
this
.
options
.
startBlockNumber
}
this
.
logger
.
info
(
`starting L1 block height`
,
{
startBlockNumber
:
this
.
state
.
highestUncheckedBlockNumber
,
})
}
// K8s healthcheck
async
routes
(
router
:
ExpressRouter
):
Promise
<
void
>
{
router
.
get
(
'
/healthz
'
,
async
(
req
,
res
)
=>
{
return
res
.
status
(
200
).
json
({
ok
:
!
this
.
state
.
forgeryDetected
,
})
})
}
async
main
():
Promise
<
void
>
{
// Get current block number
let
latestL1BlockNumber
:
number
try
{
latestL1BlockNumber
=
await
this
.
options
.
l1RpcProvider
.
getBlockNumber
()
}
catch
(
err
)
{
this
.
logger
.
error
(
`got error when connecting to node`
,
{
error
:
err
,
node
:
'
l1
'
,
section
:
'
getBlockNumber
'
,
})
this
.
metrics
.
nodeConnectionFailures
.
inc
({
chainId
:
this
.
state
.
messenger
.
l1ChainId
,
section
:
'
getBlockNumber
'
,
})
await
sleep
(
this
.
options
.
sleepTimeMs
)
return
}
// See if we have a new unchecked block
if
(
latestL1BlockNumber
<=
this
.
state
.
highestUncheckedBlockNumber
)
{
// The RPC provider is behind us, wait a bit
await
sleep
(
this
.
options
.
sleepTimeMs
)
return
}
this
.
logger
.
info
(
`checking recent blocks`
,
{
fromBlockNumber
:
this
.
state
.
highestUncheckedBlockNumber
,
toBlockNumber
:
latestL1BlockNumber
,
})
// Perform the check
let
proofEvents
:
Event
[]
try
{
// The query includes events in the blockNumbers given as the last two arguments
proofEvents
=
await
this
.
state
.
messenger
.
contracts
.
l1
.
OptimismPortal
.
queryFilter
(
this
.
state
.
messenger
.
contracts
.
l1
.
OptimismPortal
.
filters
.
WithdrawalProven
(),
this
.
state
.
highestUncheckedBlockNumber
,
latestL1BlockNumber
)
}
catch
(
err
)
{
this
.
logger
.
error
(
`got error when connecting to node`
,
{
error
:
err
,
node
:
'
l1
'
,
section
:
'
querying for WithdrawalProven events
'
,
})
this
.
metrics
.
nodeConnectionFailures
.
inc
({
layer
:
'
l1
'
,
section
:
'
querying for WithdrawalProven events
'
,
})
// connection error, wait then restart
await
sleep
(
this
.
options
.
sleepTimeMs
)
return
}
for
(
const
proofEvent
of
proofEvents
)
{
const
exists
=
await
this
.
state
.
messenger
.
contracts
.
l2
.
BedrockMessagePasser
.
sentMessages
(
proofEvent
.
args
.
withdrawalHash
)
const
provenAt
=
`
${
(
dateformat
(
new
Date
(
(
await
this
.
options
.
l1RpcProvider
.
getBlock
(
proofEvent
.
blockHash
))
.
timestamp
*
1000
)
),
'
mmmm dS, yyyy, h:MM:ss TT
'
,
true
)
}
UTC`
if
(
exists
)
{
this
.
metrics
.
withdrawalsValidated
.
inc
()
this
.
logger
.
info
(
`valid withdrawal`
,
{
withdrawalHash
:
proofEvent
.
args
.
withdrawalHash
,
provenAt
,
})
}
else
{
this
.
logger
.
error
(
`withdrawalHash not seen on L2`
,
{
withdrawalHash
:
proofEvent
.
args
.
withdrawalHash
,
provenAt
,
})
this
.
state
.
forgeryDetected
=
true
this
.
metrics
.
isDetectingForgeries
.
set
(
1
)
return
}
}
this
.
state
.
highestUncheckedBlockNumber
=
latestL1BlockNumber
+
1
// If we got through the above without throwing an error, we should be fine to reset.
this
.
state
.
forgeryDetected
=
false
this
.
metrics
.
isDetectingForgeries
.
set
(
0
)
}
}
if
(
require
.
main
===
module
)
{
const
service
=
new
WithdrawalMonitor
()
service
.
run
()
}
packages/sdk/.eslintrc.js
View file @
8d98d5d4
module
.
exports
=
{
module
.
exports
=
{
extends
:
'
../../.eslintrc.js
'
,
extends
:
'
../../.eslintrc.js
'
,
overrides
:
[
{
files
:
[
'
src/**/*.ts
'
],
rules
:
{
'
no-restricted-imports
'
:
[
'
error
'
,
'
assert
'
,
'
buffer
'
,
'
child_process
'
,
'
cluster
'
,
'
crypto
'
,
'
dgram
'
,
'
dns
'
,
'
domain
'
,
'
events
'
,
'
freelist
'
,
'
fs
'
,
'
http
'
,
'
https
'
,
'
module
'
,
'
net
'
,
'
os
'
,
'
path
'
,
'
punycode
'
,
'
querystring
'
,
'
readline
'
,
'
repl
'
,
'
smalloc
'
,
'
stream
'
,
'
string_decoder
'
,
'
sys
'
,
'
timers
'
,
'
tls
'
,
'
tracing
'
,
'
tty
'
,
'
url
'
,
'
util
'
,
'
vm
'
,
'
zlib
'
,
],
},
},
],
}
}
packages/sdk/src/l2-provider.ts
View file @
8d98d5d4
import
assert
from
'
assert
'
import
{
Provider
,
TransactionRequest
}
from
'
@ethersproject/abstract-provider
'
import
{
Provider
,
TransactionRequest
}
from
'
@ethersproject/abstract-provider
'
import
{
serialize
}
from
'
@ethersproject/transactions
'
import
{
serialize
}
from
'
@ethersproject/transactions
'
import
{
Contract
,
BigNumber
}
from
'
ethers
'
import
{
Contract
,
BigNumber
}
from
'
ethers
'
import
{
predeploys
,
getContractInterface
}
from
'
@eth-optimism/contracts
'
import
{
predeploys
,
getContractInterface
}
from
'
@eth-optimism/contracts
'
import
cloneDeep
from
'
lodash/cloneDeep
'
import
cloneDeep
from
'
lodash/cloneDeep
'
import
{
assert
}
from
'
./utils/assert
'
import
{
L2Provider
,
ProviderLike
,
NumberLike
}
from
'
./interfaces
'
import
{
L2Provider
,
ProviderLike
,
NumberLike
}
from
'
./interfaces
'
import
{
toProvider
,
toNumber
,
toBigNumber
}
from
'
./utils
'
import
{
toProvider
,
toNumber
,
toBigNumber
}
from
'
./utils
'
...
...
packages/sdk/src/utils/assert.ts
0 → 100644
View file @
8d98d5d4
export
const
assert
=
(
condition
:
boolean
,
message
:
string
):
void
=>
{
if
(
!
condition
)
{
throw
new
Error
(
message
)
}
}
packages/sdk/src/utils/coercion.ts
View file @
8d98d5d4
import
assert
from
'
assert
'
import
{
import
{
Provider
,
Provider
,
TransactionReceipt
,
TransactionReceipt
,
...
@@ -8,6 +6,7 @@ import {
...
@@ -8,6 +6,7 @@ import {
import
{
Signer
}
from
'
@ethersproject/abstract-signer
'
import
{
Signer
}
from
'
@ethersproject/abstract-signer
'
import
{
ethers
,
BigNumber
}
from
'
ethers
'
import
{
ethers
,
BigNumber
}
from
'
ethers
'
import
{
assert
}
from
'
./assert
'
import
{
import
{
SignerOrProviderLike
,
SignerOrProviderLike
,
ProviderLike
,
ProviderLike
,
...
...
specs/bridges.md
View file @
8d98d5d4
...
@@ -22,7 +22,6 @@ The `L2StandardBridge` is a predeploy contract located at
...
@@ -22,7 +22,6 @@ The `L2StandardBridge` is a predeploy contract located at
```
solidity
```
solidity
interface StandardBridge {
interface StandardBridge {
event ERC20BridgeFinalized(address indexed localToken, address indexed remoteToken, address indexed from, address to, uint256 amount, bytes extraData);
event ERC20BridgeFinalized(address indexed localToken, address indexed remoteToken, address indexed from, address to, uint256 amount, bytes extraData);
event ERC20BridgeFinalized(address indexed localToken, address indexed remoteToken, address indexed from, address to, uint256 amount, bytes extraData);
event ERC20BridgeInitiated(address indexed localToken, address indexed remoteToken, address indexed from, address to, uint256 amount, bytes extraData);
event ERC20BridgeInitiated(address indexed localToken, address indexed remoteToken, address indexed from, address to, uint256 amount, bytes extraData);
event ETHBridgeFinalized(address indexed from, address indexed to, uint256 amount, bytes extraData);
event ETHBridgeFinalized(address indexed from, address indexed to, uint256 amount, bytes extraData);
...
...
specs/derivation.md
View file @
8d98d5d4
...
@@ -710,6 +710,8 @@ enact the change, as linear rewinds of the tip of the chain may not be supported
...
@@ -710,6 +710,8 @@ enact the change, as linear rewinds of the tip of the chain may not be supported
#### L1-sync: payload attributes processing
#### L1-sync: payload attributes processing
[
exec-engine-comm
]:
exec-engine.md#engine-api
If the safe and unsafe L2 heads are identical (whether because of failed consolidation or not), we send the L2 payload
If the safe and unsafe L2 heads are identical (whether because of failed consolidation or not), we send the L2 payload
attributes to the execution engine to be constructed into a proper L2 block.
attributes to the execution engine to be constructed into a proper L2 block.
This L2 block will then become both the new L2 safe and unsafe head.
This L2 block will then become both the new L2 safe and unsafe head.
...
@@ -728,6 +730,7 @@ The payload attributes are then processed with a sequence of:
...
@@ -728,6 +730,7 @@ The payload attributes are then processed with a sequence of:
-
`engine_forkchoiceUpdatedV1`
with current forkchoice state of the stage, and the attributes to start block building.
-
`engine_forkchoiceUpdatedV1`
with current forkchoice state of the stage, and the attributes to start block building.
-
Non-deterministic sources, like the tx-pool, must be disabled to reconstruct the expected block.
-
Non-deterministic sources, like the tx-pool, must be disabled to reconstruct the expected block.
-
`engine_getPayload`
to retrieve the payload, by the payload-ID in the result of the previous step.
-
`engine_getPayload`
to retrieve the payload, by the payload-ID in the result of the previous step.
-
`engine_newPayload`
to import the new payload into the execution engine.
-
`engine_forkchoiceUpdatedV1`
to make the new payload canonical,
-
`engine_forkchoiceUpdatedV1`
to make the new payload canonical,
now with a change of both
`safe`
and
`unsafe`
fields to refer to the payload, and no payload attributes.
now with a change of both
`safe`
and
`unsafe`
fields to refer to the payload, and no payload attributes.
...
...
specs/withdrawals.md
View file @
8d98d5d4
...
@@ -133,8 +133,8 @@ The Optimism Portal serves as both the entry and exit point to the Optimism L2.
...
@@ -133,8 +133,8 @@ The Optimism Portal serves as both the entry and exit point to the Optimism L2.
the
[
DepositFeed
](
./deposits.md#deposit-contract
)
contract, and in addition provides the following interface for
the
[
DepositFeed
](
./deposits.md#deposit-contract
)
contract, and in addition provides the following interface for
withdrawals:
withdrawals:
-
[
WithdrawalTransaction type
](
https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/contracts/libraries/Types.sol#L46-L56
)
-
[
`WithdrawalTransaction` type
](
https://github.com/ethereum-optimism/optimism/blob/6c6d142d7bb95faa11066aab5d8aed7187abfe38/packages/contracts-bedrock/contracts/libraries/Types.sol#L76-L83
)
-
[
OutputRootProof type
](
https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/contracts/libraries/Types.sol#L20-L29
)
-
[
`OutputRootProof` type
](
https://github.com/ethereum-optimism/optimism/blob/6c6d142d7bb95faa11066aab5d8aed7187abfe38/packages/contracts-bedrock/contracts/libraries/Types.sol#L33-L38
)
```
js
```
js
interface
OptimismPortal
{
interface
OptimismPortal
{
...
@@ -184,7 +184,7 @@ These inputs must satisfy the following conditions:
...
@@ -184,7 +184,7 @@ These inputs must satisfy the following conditions:
### Key Properties of Withdrawal Verification
### Key Properties of Withdrawal Verification
1.
It should not be possible 'double spend' a withdrawal, ie. to relay a withdrawal on L1 which does not
1.
It should not be possible
to
'double spend' a withdrawal, ie. to relay a withdrawal on L1 which does not
correspond to a message initiated on L2. For reference, see
[
this writeup
][
polygon-dbl-spend
]
of a vulnerability
correspond to a message initiated on L2. For reference, see
[
this writeup
][
polygon-dbl-spend
]
of a vulnerability
of this type found on Polygon.
of this type found on Polygon.
...
...
yarn.lock
View file @
8d98d5d4
...
@@ -10580,9 +10580,9 @@ http-basic@^8.1.1:
...
@@ -10580,9 +10580,9 @@ http-basic@^8.1.1:
parse-cache-control "^1.0.1"
parse-cache-control "^1.0.1"
http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0:
http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0:
version "4.1.
0
"
version "4.1.
1
"
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.
0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390
"
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.
1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a
"
integrity sha512-
carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8c
Q==
integrity sha512-
er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYX
Q==
http-errors@1.7.2:
http-errors@1.7.2:
version "1.7.2"
version "1.7.2"
...
...
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