Commit 926ba712 authored by Joshua Gutow's avatar Joshua Gutow Committed by GitHub

plasma mode: Specify valid commitment type (#10622)

* op-node: Better logging in commitment tracking

* op-node: Properly handle differences in Keccak vs Generic Commitments

* Use daCommitmentType in deploy config

* da-server: Add option to use generic commitments

* CI: Add generic commitment

* op-chain-ops: Set daCommitmentType in testdata

* Fix comm type check

* Fix CI env var

* Set proper default for daCommitmentType

* Use string for daCommitmentType

* Use bytes cast instead of abi.encodePacked
parent 0221590b
......@@ -224,6 +224,12 @@ jobs:
- run:
name: Copy Plasma allocs to .devnet-plasma
command: cp -r .devnet/ .devnet-plasma/
- run:
name: Generate Generic Plasma allocs
command: DEVNET_PLASMA="true" GENERIC_PLASMA="true" make devnet-allocs
- run:
name: Copy Plasma allocs to .devnet-plasma
command: cp -r .devnet/ .devnet-plasma-generic/
- run:
name: Generate non-FPAC allocs
command: make devnet-allocs
......@@ -251,6 +257,11 @@ jobs:
- ".devnet-plasma/allocs-l2.json"
- ".devnet-plasma/allocs-l2-delta.json"
- ".devnet-plasma/allocs-l2-ecotone.json"
- ".devnet-plasma-generic/allocs-l1.json"
- ".devnet-plasma-generic/addresses.json"
- ".devnet-plasma-generic/allocs-l2.json"
- ".devnet-plasma-generic/allocs-l2-delta.json"
- ".devnet-plasma-generic/allocs-l2-ecotone.json"
- "packages/contracts-bedrock/deploy-config/devnetL1.json"
- "packages/contracts-bedrock/deployments/devnetL1"
- notify-failures-on-develop
......@@ -1270,6 +1281,16 @@ jobs:
- run:
name: Set DEVNET_PLASMA = true
command: echo 'export DEVNET_PLASMA=true' >> $BASH_ENV
- when:
condition:
equal: ['plasma-generic', <<parameters.fpac>>]
steps:
- run:
name: Set DEVNET_PLASMA = true
command: echo 'export DEVNET_PLASMA=true' >> $BASH_ENV
- run:
name: Set GENERIC_PLASMA = true
command: echo 'export GENERIC_PLASMA=true' >> $BASH_ENV
- check-changed:
patterns: op-(.+),packages,ops-bedrock,bedrock-devnet
- run:
......@@ -1878,7 +1899,7 @@ workflows:
- devnet:
matrix:
parameters:
fpac: ["legacy", "fault-proofs", "plasma"]
fpac: ["legacy", "fault-proofs", "plasma", "plasma-generic"]
requires:
- pnpm-monorepo
- op-batcher-docker-build
......
......@@ -30,6 +30,7 @@ log = logging.getLogger()
DEVNET_NO_BUILD = os.getenv('DEVNET_NO_BUILD') == "true"
DEVNET_FPAC = os.getenv('DEVNET_FPAC') == "true"
DEVNET_PLASMA = os.getenv('DEVNET_PLASMA') == "true"
GENERIC_PLASMA = os.getenv('GENERIC_PLASMA') == "true"
class Bunch:
def __init__(self, **kwds):
......@@ -135,6 +136,8 @@ def init_devnet_l1_deploy_config(paths, update_timestamp=False):
deploy_config['faultGameWithdrawalDelay'] = 0
if DEVNET_PLASMA:
deploy_config['usePlasma'] = True
if GENERIC_PLASMA:
deploy_config['daCommitmentType'] = "GenericCommitment"
write_json(paths.devnet_config_path, deploy_config)
def devnet_l1_allocs(paths):
......@@ -273,11 +276,17 @@ def devnet_deploy(paths):
if DEVNET_PLASMA:
docker_env['PLASMA_ENABLED'] = 'true'
docker_env['PLASMA_DA_SERVICE'] = 'false'
else:
docker_env['PLASMA_ENABLED'] = 'false'
if GENERIC_PLASMA:
docker_env['PLASMA_GENERIC_DA'] = 'true'
docker_env['PLASMA_DA_SERVICE'] = 'true'
else:
docker_env['PLASMA_GENERIC_DA'] = 'false'
docker_env['PLASMA_DA_SERVICE'] = 'false'
# Bring up the rest of the services.
log.info('Bringing up `op-node`, `op-proposer` and `op-batcher`.')
run_command(['docker', 'compose', 'up', '-d', 'op-node', 'op-proposer', 'op-batcher', 'artifact-server'], cwd=paths.ops_bedrock_dir, env=docker_env)
......@@ -287,7 +296,7 @@ def devnet_deploy(paths):
log.info('Bringing up `op-challenger`.')
run_command(['docker', 'compose', 'up', '-d', 'op-challenger'], cwd=paths.ops_bedrock_dir, env=docker_env)
# Optionally bring up OP Plasma.
# Optionally bring up Plasma Mode components.
if DEVNET_PLASMA:
log.info('Bringing up `da-server`, `sentinel`.') # TODO(10141): We don't have public sentinel images yet
run_command(['docker', 'compose', 'up', '-d', 'da-server'], cwd=paths.ops_bedrock_dir, env=docker_env)
......
......@@ -21,6 +21,7 @@ import (
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum-optimism/optimism/op-node/rollup"
plasma "github.com/ethereum-optimism/optimism/op-plasma"
"github.com/ethereum-optimism/optimism/op-service/eth"
)
......@@ -271,6 +272,8 @@ type DeployConfig struct {
CustomGasTokenAddress common.Address `json:"customGasTokenAddress"`
// UsePlasma is a flag that indicates if the system is using op-plasma
UsePlasma bool `json:"usePlasma"`
// DACommitmentType specifies the allowed commitment
DACommitmentType string `json:"daCommitmentType"`
// DAChallengeWindow represents the block interval during which the availability of a data commitment can be challenged.
DAChallengeWindow uint64 `json:"daChallengeWindow"`
// DAResolveWindow represents the block interval during which a data availability challenge can be resolved.
......@@ -443,6 +446,9 @@ func (d *DeployConfig) Check() error {
if d.DAResolveWindow == 0 {
return fmt.Errorf("%w: DAResolveWindow cannot be 0 when using plasma mode", ErrInvalidDeployConfig)
}
if !(d.DACommitmentType == plasma.KeccakCommitmentString || d.DACommitmentType == plasma.GenericCommitmentString) {
return fmt.Errorf("%w: DACommitmentType must be either KeccakCommtiment or GenericCommitment", ErrInvalidDeployConfig)
}
}
if d.UseCustomGasToken {
if d.CustomGasTokenAddress == (common.Address{}) {
......@@ -513,9 +519,10 @@ func (d *DeployConfig) CheckAddresses() error {
if d.OptimismPortalProxy == (common.Address{}) {
return fmt.Errorf("%w: OptimismPortalProxy cannot be address(0)", ErrInvalidDeployConfig)
}
if d.UsePlasma && d.DAChallengeProxy == (common.Address{}) {
if d.UsePlasma && d.DACommitmentType == plasma.KeccakCommitmentString && d.DAChallengeProxy == (common.Address{}) {
return fmt.Errorf("%w: DAChallengeContract cannot be address(0) when using plasma mode", ErrInvalidDeployConfig)
} else if d.UsePlasma && d.DACommitmentType == plasma.GenericCommitmentString && d.DAChallengeProxy != (common.Address{}) {
return fmt.Errorf("%w: DAChallengeContract must be address(0) when using generic commitments in plasma mode", ErrInvalidDeployConfig)
}
return nil
}
......@@ -612,6 +619,7 @@ func (d *DeployConfig) RollupConfig(l1StartBlock *types.Block, l2GenesisBlockHas
var plasma *rollup.PlasmaConfig
if d.UsePlasma {
plasma = &rollup.PlasmaConfig{
CommitmentType: d.DACommitmentType,
DAChallengeAddress: d.DAChallengeProxy,
DAChallengeWindow: d.DAChallengeWindow,
DAResolveWindow: d.DAResolveWindow,
......
......@@ -88,6 +88,7 @@
"useFaultProofs": false,
"usePlasma": false,
"daBondSize": 0,
"daCommitmentType": "KeccakCommtiment",
"daChallengeProxy": "0x0000000000000000000000000000000000000000",
"daChallengeWindow": 0,
"daResolveWindow": 0,
......
......@@ -16,6 +16,7 @@ import (
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-e2e/config"
"github.com/ethereum-optimism/optimism/op-node/rollup"
plasma "github.com/ethereum-optimism/optimism/op-plasma"
"github.com/ethereum-optimism/optimism/op-service/eth"
)
......@@ -143,12 +144,13 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) *
l2Genesis.Alloc[addr] = val
}
var plasma *rollup.PlasmaConfig
var pcfg *rollup.PlasmaConfig
if deployConf.UsePlasma {
plasma = &rollup.PlasmaConfig{
pcfg = &rollup.PlasmaConfig{
DAChallengeAddress: l1Deployments.DataAvailabilityChallengeProxy,
DAChallengeWindow: deployConf.DAChallengeWindow,
DAResolveWindow: deployConf.DAResolveWindow,
CommitmentType: plasma.KeccakCommitmentString,
}
}
......@@ -180,7 +182,7 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) *
EcotoneTime: deployConf.EcotoneTime(uint64(deployConf.L1GenesisBlockTimestamp)),
FjordTime: deployConf.FjordTime(uint64(deployConf.L1GenesisBlockTimestamp)),
InteropTime: deployConf.InteropTime(uint64(deployConf.L1GenesisBlockTimestamp)),
PlasmaConfig: plasma,
PlasmaConfig: pcfg,
}
require.NoError(t, rollupCfg.Check())
......
......@@ -9,6 +9,7 @@ import (
"testing"
"github.com/ethereum-optimism/optimism/op-node/node/safedb"
plasma "github.com/ethereum-optimism/optimism/op-plasma"
"github.com/holiman/uint256"
"github.com/stretchr/testify/require"
......@@ -1256,6 +1257,7 @@ func TestPlasmaFinalityData(t *testing.T) {
plasmaCfg := &rollup.PlasmaConfig{
DAChallengeWindow: 90,
DAResolveWindow: 90,
CommitmentType: plasma.KeccakCommitmentString,
}
// shoud return l1 finality if plasma is not enabled
require.Equal(t, uint64(finalityLookback), calcFinalityLookback(cfg))
......
......@@ -92,7 +92,7 @@ func (s *PlasmaDataSource) Next(ctx context.Context) (eth.Data, error) {
return nil, NewTemporaryError(fmt.Errorf("failed to fetch input data with comm %x from da service: %w", s.comm, err))
}
// inputs are limited to a max size to ensure they can be challenged in the DA contract.
if len(data) > plasma.MaxInputSize {
if s.comm.CommitmentType() == plasma.Keccak256CommitmentType && len(data) > plasma.MaxInputSize {
s.log.Warn("input data exceeds max size", "size", len(data), "max", plasma.MaxInputSize)
s.comm = nil
return s.Next(ctx)
......
......@@ -91,6 +91,7 @@ func TestPlasmaDataSource(t *testing.T) {
PlasmaConfig: &rollup.PlasmaConfig{
DAChallengeWindow: pcfg.ChallengeWindow,
DAResolveWindow: pcfg.ResolveWindow,
CommitmentType: plasma.KeccakCommitmentString,
},
}
// keep track of random input data to validate against
......@@ -333,6 +334,7 @@ func TestPlasmaDataSourceStall(t *testing.T) {
PlasmaConfig: &rollup.PlasmaConfig{
DAChallengeWindow: pcfg.ChallengeWindow,
DAResolveWindow: pcfg.ResolveWindow,
CommitmentType: plasma.KeccakCommitmentString,
},
}
......@@ -451,6 +453,7 @@ func TestPlasmaDataSourceInvalidData(t *testing.T) {
PlasmaConfig: &rollup.PlasmaConfig{
DAChallengeWindow: pcfg.ChallengeWindow,
DAResolveWindow: pcfg.ResolveWindow,
CommitmentType: plasma.KeccakCommitmentString,
},
}
......
......@@ -52,6 +52,8 @@ type Genesis struct {
type PlasmaConfig struct {
// L1 DataAvailabilityChallenge contract proxy address
DAChallengeAddress common.Address `json:"da_challenge_contract_address,omitempty"`
// CommitmentType specifies which commitment type can be used. Defaults to Keccak (type 0) if not present
CommitmentType string `json:"da_commitment_type"`
// DA challenge window value set on the DAC contract. Used in plasma mode
// to compute when a commitment can no longer be challenged.
DAChallengeWindow uint64 `json:"da_challenge_window"`
......@@ -345,6 +347,18 @@ func validatePlasmaConfig(cfg *Config) error {
if cfg.LegacyDAResolveWindow != cfg.PlasmaConfig.DAResolveWindow {
return fmt.Errorf("LegacyDAResolveWindow (%v) != PlasmaConfig.DAResolveWindow (%v)", cfg.LegacyDAResolveWindow, cfg.PlasmaConfig.DAResolveWindow)
}
if cfg.PlasmaConfig.CommitmentType != plasma.KeccakCommitmentString {
return errors.New("Cannot set CommitmentType with the legacy config")
}
} else if cfg.PlasmaConfig != nil {
if !(cfg.PlasmaConfig.CommitmentType == plasma.KeccakCommitmentString || cfg.PlasmaConfig.CommitmentType == plasma.GenericCommitmentString) {
return fmt.Errorf("invalid commitment type: %v", cfg.PlasmaConfig.CommitmentType)
}
if cfg.PlasmaConfig.CommitmentType == plasma.KeccakCommitmentString && cfg.PlasmaConfig.DAChallengeAddress == (common.Address{}) {
return errors.New("Must set da_challenge_contract_address for keccak commitments")
} else if cfg.PlasmaConfig.CommitmentType == plasma.GenericCommitmentString && cfg.PlasmaConfig.DAChallengeAddress != (common.Address{}) {
return errors.New("Must set empty da_challenge_contract_address for generic commitments")
}
}
return nil
}
......@@ -485,19 +499,21 @@ func (c *Config) GetOPPlasmaConfig() (plasma.Config, error) {
if c.PlasmaConfig == nil {
return plasma.Config{}, errors.New("no plasma config")
}
if c.PlasmaConfig.DAChallengeAddress == (common.Address{}) {
return plasma.Config{}, errors.New("missing DAChallengeAddress")
}
if c.PlasmaConfig.DAChallengeWindow == uint64(0) {
return plasma.Config{}, errors.New("missing DAChallengeWindow")
}
if c.PlasmaConfig.DAResolveWindow == uint64(0) {
return plasma.Config{}, errors.New("missing DAResolveWindow")
}
t, err := plasma.CommitmentTypeFromString(c.PlasmaConfig.CommitmentType)
if err != nil {
return plasma.Config{}, err
}
return plasma.Config{
DAChallengeContractAddress: c.PlasmaConfig.DAChallengeAddress,
ChallengeWindow: c.PlasmaConfig.DAChallengeWindow,
ResolveWindow: c.PlasmaConfig.DAResolveWindow,
CommitmentType: t,
}, nil
}
......@@ -550,6 +566,9 @@ func (c *Config) Description(l2Chains map[string]string) string {
banner += fmt.Sprintf(" - Interop: %s\n", fmtForkTimeOrUnset(c.InteropTime))
// Report the protocol version
banner += fmt.Sprintf("Node supports up to OP-Stack Protocol Version: %s\n", OPStackSupport)
if c.PlasmaConfig != nil {
banner += fmt.Sprintf("Node supports Plasma Mode with CommitmentType %v\n", c.PlasmaConfig.CommitmentType)
}
return banner
}
......@@ -569,6 +588,7 @@ func (c *Config) LogDescription(log log.Logger, l2Chains map[string]string) {
if networkL1 == "" {
networkL1 = "unknown L1"
}
log.Info("Rollup Config", "l2_chain_id", c.L2ChainID, "l2_network", networkL2, "l1_chain_id", c.L1ChainID,
"l1_network", networkL1, "l2_start_time", c.Genesis.L2Time, "l2_block_hash", c.Genesis.L2.Hash.String(),
"l2_block_number", c.Genesis.L2.Number, "l1_block_hash", c.Genesis.L1.Hash.String(),
......@@ -578,6 +598,7 @@ func (c *Config) LogDescription(log log.Logger, l2Chains map[string]string) {
"ecotone_time", fmtForkTimeOrUnset(c.EcotoneTime),
"fjord_time", fmtForkTimeOrUnset(c.FjordTime),
"interop_time", fmtForkTimeOrUnset(c.InteropTime),
"plasma_mode", c.PlasmaConfig != nil,
)
}
......
......@@ -41,7 +41,7 @@ func StartDAServer(cliCtx *cli.Context) error {
store = s3
}
server := plasma.NewDAServer(cliCtx.String(ListenAddrFlagName), cliCtx.Int(PortFlagName), store, l)
server := plasma.NewDAServer(cliCtx.String(ListenAddrFlagName), cliCtx.Int(PortFlagName), store, l, cfg.UseGenericComm)
if err := server.Start(); err != nil {
return fmt.Errorf("failed to start the DA server")
......
......@@ -18,6 +18,7 @@ const (
S3AccessKeyIDFlagName = "s3.access-key-id"
S3AccessKeySecretFlagName = "s3.access-key-secret"
FileStorePathFlagName = "file.path"
GenericCommFlagName = "generic-commitment"
)
const EnvVarPrefix = "OP_PLASMA_DA_SERVER"
......@@ -44,6 +45,12 @@ var (
Usage: "path to directory for file storage",
EnvVars: prefixEnvVars("FILESTORE_PATH"),
}
GenericCommFlag = &cli.BoolFlag{
Name: GenericCommFlagName,
Usage: "enable generic commitments for testing. Not for production use.",
EnvVars: prefixEnvVars("GENERIC_COMMITMENT"),
Value: false,
}
S3BucketFlag = &cli.StringFlag{
Name: S3BucketFlagName,
Usage: "bucket name for S3 storage",
......@@ -80,6 +87,7 @@ var optionalFlags = []cli.Flag{
S3EndpointFlag,
S3AccessKeyIDFlag,
S3AccessKeySecretFlag,
GenericCommFlag,
}
func init() {
......@@ -96,6 +104,7 @@ type CLIConfig struct {
S3Endpoint string
S3AccessKeyID string
S3AccessKeySecret string
UseGenericComm bool
}
func ReadCLIConfig(ctx *cli.Context) CLIConfig {
......@@ -105,6 +114,7 @@ func ReadCLIConfig(ctx *cli.Context) CLIConfig {
S3Endpoint: ctx.String(S3EndpointFlagName),
S3AccessKeyID: ctx.String(S3AccessKeyIDFlagName),
S3AccessKeySecret: ctx.String(S3AccessKeySecretFlagName),
UseGenericComm: ctx.Bool(GenericCommFlagName),
}
}
......
......@@ -3,6 +3,7 @@ package plasma
import (
"bytes"
"errors"
"fmt"
"github.com/ethereum/go-ethereum/crypto"
)
......@@ -16,12 +17,25 @@ var ErrCommitmentMismatch = errors.New("commitment mismatch")
// CommitmentType is the commitment type prefix.
type CommitmentType byte
func CommitmentTypeFromString(s string) (CommitmentType, error) {
switch s {
case KeccakCommitmentString:
return Keccak256CommitmentType, nil
case GenericCommitmentString:
return GenericCommitmentType, nil
default:
return 0, fmt.Errorf("invalid commitment type: %s", s)
}
}
// CommitmentType describes the binary format of the commitment.
// KeccakCommitmentType is the default commitment type for the centralized DA storage.
// KeccakCommitmentStringType is the default commitment type for the centralized DA storage.
// GenericCommitmentType indicates an opaque bytestring that the op-node never opens.
const (
Keccak256CommitmentType CommitmentType = 0
GenericCommitmentType CommitmentType = 1
KeccakCommitmentString string = "KeccakCommitment"
GenericCommitmentString string = "GenericCommitment"
)
// CommitmentData is the binary representation of a commitment.
......
......@@ -130,7 +130,7 @@ func (c *DAClient) setInput(ctx context.Context, img []byte) (CommitmentData, er
return nil, err
}
comm, err := DecodeGenericCommitment(b)
comm, err := DecodeCommitmentData(b)
if err != nil {
return nil, err
}
......
......@@ -51,7 +51,7 @@ func TestDAClientPrecomputed(t *testing.T) {
ctx := context.Background()
server := NewDAServer("127.0.0.1", 0, store, logger)
server := NewDAServer("127.0.0.1", 0, store, logger, false)
require.NoError(t, server.Start())
......@@ -108,7 +108,7 @@ func TestDAClientService(t *testing.T) {
ctx := context.Background()
server := NewDAServer("127.0.0.1", 0, store, logger)
server := NewDAServer("127.0.0.1", 0, store, logger, false)
require.NoError(t, server.Start())
......
......@@ -51,6 +51,8 @@ type HeadSignalFn func(eth.L1BlockRef)
type Config struct {
// Required for filtering contract events
DAChallengeContractAddress common.Address
// Allowed CommitmentType
CommitmentType CommitmentType
// The number of l1 blocks after the input is committed during which one can challenge.
ChallengeWindow uint64
// The number of l1 blocks after a commitment is challenged during which one can resolve.
......@@ -166,6 +168,10 @@ func (d *DA) Reset(ctx context.Context, base eth.L1BlockRef, baseCfg eth.SystemC
// GetInput returns the input data for the given commitment bytes. blockNumber is required to lookup
// the challenge status in the DataAvailabilityChallenge L1 contract.
func (d *DA) GetInput(ctx context.Context, l1 L1Fetcher, comm CommitmentData, blockId eth.BlockID) (eth.Data, error) {
// If it's not the right commitment type, report it as an expired commitment in order to skip it
if d.cfg.CommitmentType != comm.CommitmentType() {
return nil, fmt.Errorf("invalid commitment type; expected: %v, got: %v: %w", d.cfg.CommitmentType, comm.CommitmentType(), ErrExpiredChallenge)
}
// If the challenge head is ahead in the case of a pipeline reset or stall, we might have synced a
// challenge event for this commitment. Otherwise we mark the commitment as part of the canonical
// chain so potential future challenge events can be selected.
......@@ -205,6 +211,10 @@ func (d *DA) GetInput(ctx context.Context, l1 L1Fetcher, comm CommitmentData, bl
if !notFound {
return data, nil
}
// Generic Commitments don't resolve from L1 so if we still can't find the data with out of luck
if comm.CommitmentType() == GenericCommitmentType {
return nil, ErrMissingPastWindow
}
// data not found in storage, return from challenge resolved input
resolvedInput, err := d.state.GetResolvedInput(comm.Encode())
if err != nil {
......@@ -310,31 +320,39 @@ func (d *DA) LoadChallengeEvents(ctx context.Context, l1 L1Fetcher, block eth.Bl
d.log.Error("tx hash mismatch", "block", block.Number, "txIdx", i, "log", log.Index, "txHash", tx.Hash(), "receiptTxHash", log.TxHash)
continue
}
// Decode the input from resolver tx calldata
input, err := DecodeResolvedInput(tx.Data())
if err != nil {
d.log.Error("failed to decode resolved input", "block", block.Number, "txIdx", i, "err", err)
continue
}
if err := comm.Verify(input); err != nil {
d.log.Error("failed to verify commitment", "block", block.Number, "txIdx", i, "err", err)
continue
var input []byte
if d.cfg.CommitmentType == Keccak256CommitmentType {
// Decode the input from resolver tx calldata
input, err = DecodeResolvedInput(tx.Data())
if err != nil {
d.log.Error("failed to decode resolved input", "block", block.Number, "txIdx", i, "err", err)
continue
}
if err := comm.Verify(input); err != nil {
d.log.Error("failed to verify commitment", "block", block.Number, "txIdx", i, "err", err)
continue
}
}
d.log.Debug("challenge resolved", "block", block, "txIdx", i)
d.log.Info("challenge resolved", "block", block, "txIdx", i, "comm", comm.Encode())
d.state.SetResolvedChallenge(comm.Encode(), input, log.BlockNumber)
case ChallengeActive:
d.log.Info("detected new active challenge", "block", block)
d.log.Info("detected new active challenge", "block", block, "comm", comm.Encode())
d.state.SetActiveChallenge(comm.Encode(), log.BlockNumber, d.cfg.ResolveWindow)
default:
d.log.Warn("skipping unknown challenge status", "block", block.Number, "tx", i, "log", log.Index, "status", status)
d.log.Warn("skipping unknown challenge status", "block", block.Number, "tx", i, "log", log.Index, "status", status, "comm", comm.Encode())
}
}
return nil
}
// fetchChallengeLogs returns logs for challenge events if any for the given block
func (d *DA) fetchChallengeLogs(ctx context.Context, l1 L1Fetcher, block eth.BlockID) ([]*types.Log, error) { //cached with deposits events call so not expensive
func (d *DA) fetchChallengeLogs(ctx context.Context, l1 L1Fetcher, block eth.BlockID) ([]*types.Log, error) {
var logs []*types.Log
// Don't look at the challenge contract if there is no challenge contract.
if d.cfg.CommitmentType == GenericCommitmentType {
return logs, nil
}
//cached with deposits events call so not expensive
_, receipts, err := l1.FetchReceipts(ctx, block.Hash)
if err != nil {
return nil, err
......
......@@ -2,9 +2,12 @@ package plasma
import (
"context"
"crypto/rand"
"encoding/hex"
"errors"
"fmt"
"io"
"math/big"
"net"
"net/http"
"path"
......@@ -13,7 +16,6 @@ import (
"github.com/ethereum-optimism/optimism/op-service/rpc"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
)
......@@ -25,15 +27,16 @@ type KVStore interface {
}
type DAServer struct {
log log.Logger
endpoint string
store KVStore
tls *rpc.ServerTLSConfig
httpServer *http.Server
listener net.Listener
log log.Logger
endpoint string
store KVStore
tls *rpc.ServerTLSConfig
httpServer *http.Server
listener net.Listener
useGenericComm bool
}
func NewDAServer(host string, port int, store KVStore, log log.Logger) *DAServer {
func NewDAServer(host string, port int, store KVStore, log log.Logger, useGenericComm bool) *DAServer {
endpoint := net.JoinHostPort(host, strconv.Itoa(port))
return &DAServer{
log: log,
......@@ -42,6 +45,7 @@ func NewDAServer(host string, port int, store KVStore, log log.Logger) *DAServer
httpServer: &http.Server{
Addr: endpoint,
},
useGenericComm: useGenericComm,
}
}
......@@ -118,9 +122,8 @@ func (d *DAServer) HandleGet(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
func (d *DAServer) HandlePut(w http.ResponseWriter, r *http.Request) {
d.log.Info("PUT", "url", r.URL)
......@@ -138,20 +141,34 @@ func (d *DAServer) HandlePut(w http.ResponseWriter, r *http.Request) {
}
if r.URL.Path == "/put" || r.URL.Path == "/put/" { // without commitment
var comm []byte
if d.useGenericComm {
n, err := rand.Int(rand.Reader, big.NewInt(99999999999999))
if err != nil {
d.log.Error("Failed to generate commitment", "err", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
comm = append(comm, 0x01)
comm = append(comm, 0xff)
comm = append(comm, n.Bytes()...)
comm := GenericCommitment(crypto.Keccak256Hash(input).Bytes())
if err = d.store.Put(r.Context(), comm.Encode(), input); err != nil {
} else {
comm = NewKeccak256Commitment(input).Encode()
}
if err = d.store.Put(r.Context(), comm, input); err != nil {
d.log.Error("Failed to store commitment to the DA server", "err", err, "comm", comm)
w.WriteHeader(http.StatusInternalServerError)
return
}
d.log.Info("stored commitment", "key", hex.EncodeToString(comm), "input_len", len(input))
if _, err := w.Write(comm); err != nil {
d.log.Error("Failed to write commitment request body", "err", err, "comm", comm)
w.WriteHeader(http.StatusInternalServerError)
return
}
} else {
key := path.Base(r.URL.Path)
comm, err := hexutil.Decode(key)
......@@ -166,10 +183,8 @@ func (d *DAServer) HandlePut(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
w.WriteHeader(http.StatusOK)
}
func (b *DAServer) Endpoint() string {
......
......@@ -206,6 +206,7 @@ services:
--addr=0.0.0.0
--port=3100
--log.level=debug
--generic-commitment="${PLASMA_GENERIC_DA}"
ports:
- "3100:3100"
volumes:
......
......@@ -66,6 +66,7 @@
"respectedGameType": 0,
"useFaultProofs": false,
"usePlasma": false,
"daCommitmentType": "KeccakCommitment",
"daChallengeWindow": 160,
"daResolveWindow": 160,
"daBondSize": 1000000,
......
......@@ -288,7 +288,11 @@ contract Deploy is Deployer {
setupSuperchain();
console.log("set up superchain!");
if (cfg.usePlasma()) {
setupOpPlasma();
bytes32 typeHash = keccak256(bytes(cfg.daCommitmentType()));
bytes32 keccakHash = keccak256(bytes("KeccakCommitment"));
if (typeHash == keccakHash) {
setupOpPlasma();
}
}
setupOpChain();
console.log("set up op chain!");
......
......@@ -69,6 +69,7 @@ contract DeployConfig is Script {
uint256 public respectedGameType;
bool public useFaultProofs;
bool public usePlasma;
string public daCommitmentType;
uint256 public daChallengeWindow;
uint256 public daResolveWindow;
uint256 public daBondSize;
......@@ -147,6 +148,7 @@ contract DeployConfig is Script {
preimageOracleChallengePeriod = stdJson.readUint(_json, "$.preimageOracleChallengePeriod");
usePlasma = _readOr(_json, "$.usePlasma", false);
daCommitmentType = _readOr(_json, "$.daCommitmentType", "KeccakCommitment");
daChallengeWindow = _readOr(_json, "$.daChallengeWindow", 1000);
daResolveWindow = _readOr(_json, "$.daResolveWindow", 1000);
daBondSize = _readOr(_json, "$.daBondSize", 1000000000);
......@@ -232,4 +234,16 @@ contract DeployConfig is Script {
function _readOr(string memory json, string memory key, address defaultValue) internal view returns (address) {
return vm.keyExists(json, key) ? stdJson.readAddress(json, key) : defaultValue;
}
function _readOr(
string memory json,
string memory key,
string memory defaultValue
)
internal
view
returns (string memory)
{
return vm.keyExists(json, key) ? stdJson.readString(json, key) : defaultValue;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment