Skip to content

Commit

Permalink
Merge branch 'master' into log-connection-error
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuacolvin0 authored Sep 28, 2023
2 parents bbc046f + 88b10f1 commit 3a48bd8
Show file tree
Hide file tree
Showing 16 changed files with 102 additions and 40 deletions.
5 changes: 2 additions & 3 deletions arbcompress/compress_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@

package arbcompress

const LEVEL_FAST = 0
const LEVEL_WELL = 11
const WINDOW_SIZE = 22 // BROTLI_DEFAULT_WINDOW

func compressedBufferSizeFor(length int) int {
return length + (length>>10)*8 + 64 // actual limit is: length + (length >> 14) * 4 + 6
}

func CompressFast(input []byte) ([]byte, error) {
return compressLevel(input, LEVEL_FAST)
func CompressLevel(input []byte, level int) ([]byte, error) {
return compressLevel(input, level)
}
2 changes: 1 addition & 1 deletion arbcompress/compress_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func testCompressDecompress(t *testing.T, data []byte) {
}
testDecompress(t, compressedWell, data)

compressedFast, err := CompressFast(data)
compressedFast, err := CompressLevel(data, 0)
if err != nil {
t.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion arbitrator/prover/test-cases/go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func MerkleSample(data [][]byte, toproove int) (bool, error) {
}

func testCompression(data []byte) {
compressed, err := arbcompress.CompressFast(data)
compressed, err := arbcompress.CompressLevel(data, 0)
if err != nil {
panic(err)
}
Expand Down
6 changes: 5 additions & 1 deletion arbnode/execution/tx_pre_checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,11 @@ func PreCheckTx(bc *core.BlockChain, chainConfig *params.ChainConfig, header *ty
if config.Strictness >= TxPreCheckerStrictnessFullValidation && tx.Nonce() > stateNonce {
return MakeNonceError(sender, tx.Nonce(), stateNonce)
}
dataCost, _ := arbos.L1PricingState().GetPosterInfo(tx, l1pricing.BatchPosterAddress)
brotliCompressionLevel, err := arbos.BrotliCompressionLevel()
if err != nil {
return fmt.Errorf("failed to get brotli compression level: %w", err)
}
dataCost, _ := arbos.L1PricingState().GetPosterInfo(tx, l1pricing.BatchPosterAddress, brotliCompressionLevel)
dataGas := arbmath.BigDiv(dataCost, header.BaseFee)
if tx.Gas() < intrinsic+dataGas.Uint64() {
return core.ErrIntrinsicGas
Expand Down
61 changes: 44 additions & 17 deletions arbos/arbosState/arbosstate.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"

"github.com/offchainlabs/nitro/arbcompress"
"github.com/offchainlabs/nitro/arbos/addressSet"
"github.com/offchainlabs/nitro/arbos/addressTable"
"github.com/offchainlabs/nitro/arbos/arbostypes"
Expand All @@ -35,23 +36,24 @@ import (
// persisted beyond the end of the test.)

type ArbosState struct {
arbosVersion uint64 // version of the ArbOS storage format and semantics
upgradeVersion storage.StorageBackedUint64 // version we're planning to upgrade to, or 0 if not planning to upgrade
upgradeTimestamp storage.StorageBackedUint64 // when to do the planned upgrade
networkFeeAccount storage.StorageBackedAddress
l1PricingState *l1pricing.L1PricingState
l2PricingState *l2pricing.L2PricingState
retryableState *retryables.RetryableState
addressTable *addressTable.AddressTable
chainOwners *addressSet.AddressSet
sendMerkle *merkleAccumulator.MerkleAccumulator
blockhashes *blockhash.Blockhashes
chainId storage.StorageBackedBigInt
chainConfig storage.StorageBackedBytes
genesisBlockNum storage.StorageBackedUint64
infraFeeAccount storage.StorageBackedAddress
backingStorage *storage.Storage
Burner burn.Burner
arbosVersion uint64 // version of the ArbOS storage format and semantics
upgradeVersion storage.StorageBackedUint64 // version we're planning to upgrade to, or 0 if not planning to upgrade
upgradeTimestamp storage.StorageBackedUint64 // when to do the planned upgrade
networkFeeAccount storage.StorageBackedAddress
l1PricingState *l1pricing.L1PricingState
l2PricingState *l2pricing.L2PricingState
retryableState *retryables.RetryableState
addressTable *addressTable.AddressTable
chainOwners *addressSet.AddressSet
sendMerkle *merkleAccumulator.MerkleAccumulator
blockhashes *blockhash.Blockhashes
chainId storage.StorageBackedBigInt
chainConfig storage.StorageBackedBytes
genesisBlockNum storage.StorageBackedUint64
infraFeeAccount storage.StorageBackedAddress
brotliCompressionLevel storage.StorageBackedUint64 // brotli compression level used for pricing
backingStorage *storage.Storage
Burner burn.Burner
}

var ErrUninitializedArbOS = errors.New("ArbOS uninitialized")
Expand Down Expand Up @@ -82,6 +84,7 @@ func OpenArbosState(stateDB vm.StateDB, burner burn.Burner) (*ArbosState, error)
backingStorage.OpenStorageBackedBytes(chainConfigSubspace),
backingStorage.OpenStorageBackedUint64(uint64(genesisBlockNumOffset)),
backingStorage.OpenStorageBackedAddress(uint64(infraFeeAccountOffset)),
backingStorage.OpenStorageBackedUint64(uint64(brotliCompressionLevelOffset)),
backingStorage,
burner,
}, nil
Expand Down Expand Up @@ -139,6 +142,7 @@ const (
chainIdOffset
genesisBlockNumOffset
infraFeeAccountOffset
brotliCompressionLevelOffset
)

type SubspaceID []byte
Expand Down Expand Up @@ -215,6 +219,7 @@ func InitializeArbosState(stateDB vm.StateDB, burner burn.Burner, chainConfig *p
chainConfigStorage := sto.OpenStorageBackedBytes(chainConfigSubspace)
_ = chainConfigStorage.Set(initMessage.SerializedChainConfig)
_ = sto.SetUint64ByUint64(uint64(genesisBlockNumOffset), chainConfig.ArbitrumChainParams.GenesisBlockNum)
_ = sto.SetUint64ByUint64(uint64(brotliCompressionLevelOffset), 0) // default brotliCompressionLevel for fast compression is 0

initialRewardsRecipient := l1pricing.BatchPosterAddress
if desiredArbosVersion >= 2 {
Expand Down Expand Up @@ -318,6 +323,17 @@ func (state *ArbosState) UpgradeArbosVersion(
if !firstTime {
ensure(state.chainOwners.ClearList())
}
case 11:
if !chainConfig.DebugMode() {
// This upgrade isn't finalized so we only want to support it for testing
return fmt.Errorf(
"the chain is upgrading to unsupported ArbOS version %v, %w",
state.arbosVersion+1,
ErrFatalNodeOutOfDate,
)
}
// Update Brotli compression level for fast compression from 0 to 1
ensure(state.SetBrotliCompressionLevel(1))
default:
return fmt.Errorf(
"the chain is upgrading to unsupported ArbOS version %v, %w",
Expand Down Expand Up @@ -379,6 +395,17 @@ func (state *ArbosState) SetFormatVersion(val uint64) {
state.Restrict(state.backingStorage.SetUint64ByUint64(uint64(versionOffset), val))
}

func (state *ArbosState) BrotliCompressionLevel() (uint64, error) {
return state.brotliCompressionLevel.Get()
}

func (state *ArbosState) SetBrotliCompressionLevel(val uint64) error {
if val <= arbcompress.LEVEL_WELL {
return state.brotliCompressionLevel.Set(val)
}
return errors.New("invalid brotli compression level")
}

func (state *ArbosState) RetryableState() *retryables.RetryableState {
return state.retryableState
}
Expand Down
6 changes: 5 additions & 1 deletion arbos/block_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,11 @@ func ProduceBlockAdvanced(

if basefee.Sign() > 0 {
dataGas = math.MaxUint64
posterCost, _ := state.L1PricingState().GetPosterInfo(tx, poster)
brotliCompressionLevel, err := state.BrotliCompressionLevel()
if err != nil {
return nil, nil, fmt.Errorf("failed to get brotli compression level: %w", err)
}
posterCost, _ := state.L1PricingState().GetPosterInfo(tx, poster, brotliCompressionLevel)
posterCostInL2Gas := arbmath.BigDiv(posterCost, basefee)

if posterCostInL2Gas.IsUint64() {
Expand Down
18 changes: 9 additions & 9 deletions arbos/l1pricing/l1pricing.go
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ func (ps *L1PricingState) UpdateForBatchPosterSpending(
return nil
}

func (ps *L1PricingState) getPosterUnitsWithoutCache(tx *types.Transaction, posterAddr common.Address) uint64 {
func (ps *L1PricingState) getPosterUnitsWithoutCache(tx *types.Transaction, posterAddr common.Address, brotliCompressionLevel uint64) uint64 {

if posterAddr != BatchPosterAddress {
return 0
Expand All @@ -500,21 +500,21 @@ func (ps *L1PricingState) getPosterUnitsWithoutCache(tx *types.Transaction, post
return 0
}

l1Bytes, err := byteCountAfterBrotli0(txBytes)
l1Bytes, err := byteCountAfterBrotliLevel(txBytes, int(brotliCompressionLevel))
if err != nil {
panic(fmt.Sprintf("failed to compress tx: %v", err))
}
return l1Bytes * params.TxDataNonZeroGasEIP2028
}

// GetPosterInfo returns the poster cost and the calldata units for a transaction
func (ps *L1PricingState) GetPosterInfo(tx *types.Transaction, poster common.Address) (*big.Int, uint64) {
func (ps *L1PricingState) GetPosterInfo(tx *types.Transaction, poster common.Address, brotliCompressionLevel uint64) (*big.Int, uint64) {
if poster != BatchPosterAddress {
return common.Big0, 0
}
units := atomic.LoadUint64(&tx.CalldataUnits)
if units == 0 {
units = ps.getPosterUnitsWithoutCache(tx, poster)
units = ps.getPosterUnitsWithoutCache(tx, poster, brotliCompressionLevel)
atomic.StoreUint64(&tx.CalldataUnits, units)
}

Expand Down Expand Up @@ -570,23 +570,23 @@ func makeFakeTxForMessage(message *core.Message) *types.Transaction {
})
}

func (ps *L1PricingState) PosterDataCost(message *core.Message, poster common.Address) (*big.Int, uint64) {
func (ps *L1PricingState) PosterDataCost(message *core.Message, poster common.Address, brotliCompressionLevel uint64) (*big.Int, uint64) {
tx := message.Tx
if tx != nil {
return ps.GetPosterInfo(tx, poster)
return ps.GetPosterInfo(tx, poster, brotliCompressionLevel)
}

// Otherwise, we don't have an underlying transaction, so we're likely in gas estimation.
// We'll instead make a fake tx from the message info we do have, and then pad our cost a bit to be safe.
tx = makeFakeTxForMessage(message)
units := ps.getPosterUnitsWithoutCache(tx, poster)
units := ps.getPosterUnitsWithoutCache(tx, poster, brotliCompressionLevel)
units = arbmath.UintMulByBips(units+estimationPaddingUnits, arbmath.OneInBips+estimationPaddingBasisPoints)
pricePerUnit, _ := ps.PricePerUnit()
return am.BigMulByUint(pricePerUnit, units), units
}

func byteCountAfterBrotli0(input []byte) (uint64, error) {
compressed, err := arbcompress.CompressFast(input)
func byteCountAfterBrotliLevel(input []byte, level int) (uint64, error) {
compressed, err := arbcompress.CompressLevel(input, level)
if err != nil {
return 0, err
}
Expand Down
6 changes: 5 additions & 1 deletion arbos/tx_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,11 @@ func (p *TxProcessor) GasChargingHook(gasRemaining *uint64) (common.Address, err
// Since tips go to the network, and not to the poster, we use the basefee.
// Note, this only determines the amount of gas bought, not the price per gas.

posterCost, calldataUnits := p.state.L1PricingState().PosterDataCost(p.msg, poster)
brotliCompressionLevel, err := p.state.BrotliCompressionLevel()
if err != nil {
return common.Address{}, fmt.Errorf("failed to get brotli compression level: %w", err)
}
posterCost, calldataUnits := p.state.L1PricingState().PosterDataCost(p.msg, poster, brotliCompressionLevel)
if calldataUnits > 0 {
p.state.Restrict(p.state.L1PricingState().AddToUnitsSinceUpdate(calldataUnits))
}
Expand Down
2 changes: 1 addition & 1 deletion contracts
12 changes: 10 additions & 2 deletions nodeInterface/NodeInterface.go
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,11 @@ func (n NodeInterface) GasEstimateL1Component(
// Compute the fee paid for L1 in L2 terms
// See in GasChargingHook that this does not induce truncation error
//
feeForL1, _ := pricing.PosterDataCost(msg, l1pricing.BatchPosterAddress)
brotliCompressionLevel, err := c.State.BrotliCompressionLevel()
if err != nil {
return 0, nil, nil, fmt.Errorf("failed to get brotli compression level: %w", err)
}
feeForL1, _ := pricing.PosterDataCost(msg, l1pricing.BatchPosterAddress, brotliCompressionLevel)
feeForL1 = arbmath.BigMulByBips(feeForL1, arbos.GasEstimationL1PricePadding)
gasForL1 := arbmath.BigDiv(feeForL1, baseFee).Uint64()
return gasForL1, baseFee, l1BaseFeeEstimate, nil
Expand Down Expand Up @@ -507,7 +511,11 @@ func (n NodeInterface) GasEstimateComponents(
if err != nil {
return 0, 0, nil, nil, err
}
feeForL1, _ := pricing.PosterDataCost(msg, l1pricing.BatchPosterAddress)
brotliCompressionLevel, err := c.State.BrotliCompressionLevel()
if err != nil {
return 0, 0, nil, nil, fmt.Errorf("failed to get brotli compression level: %w", err)
}
feeForL1, _ := pricing.PosterDataCost(msg, l1pricing.BatchPosterAddress, brotliCompressionLevel)

baseFee, err := c.State.L2PricingState().BaseFeeWei()
if err != nil {
Expand Down
7 changes: 6 additions & 1 deletion nodeInterface/virtual-contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,12 @@ func init() {
return
}

posterCost, _ := state.L1PricingState().PosterDataCost(msg, l1pricing.BatchPosterAddress)
brotliCompressionLevel, err := state.BrotliCompressionLevel()
if err != nil {
log.Error("failed to get brotli compression level", "err", err)
return
}
posterCost, _ := state.L1PricingState().PosterDataCost(msg, l1pricing.BatchPosterAddress, brotliCompressionLevel)
posterCostInL2Gas := arbos.GetPosterGas(state, header.BaseFee, msg.TxRunMode, posterCost)
*gascap = arbmath.SaturatingUAdd(*gascap, posterCostInL2Gas)
}
Expand Down
4 changes: 4 additions & 0 deletions precompiles/ArbOwner.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ func (con ArbOwner) SetAmortizedCostCapBips(c ctx, evm mech, cap uint64) error {
return c.State.L1PricingState().SetAmortizedCostCapBips(cap)
}

func (con ArbOwner) SetBrotliCompressionLevel(c ctx, evm mech, level uint64) error {
return c.State.SetBrotliCompressionLevel(level)
}

func (con ArbOwner) ReleaseL1PricerSurplusFunds(c ctx, evm mech, maxWeiToRelease huge) (huge, error) {
balance := evm.StateDB.GetBalance(l1pricing.L1PricerFundsPoolAddress)
l1p := c.State.L1PricingState()
Expand Down
5 changes: 5 additions & 0 deletions precompiles/ArbOwnerPublic.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,8 @@ func (con ArbOwnerPublic) GetInfraFeeAccount(c ctx, evm mech) (addr, error) {
}
return c.State.InfraFeeAccount()
}

// GetBrotliCompressionLevel gets the current brotli compression level used for fast compression
func (con ArbOwnerPublic) GetBrotliCompressionLevel(c ctx, evm mech) (uint64, error) {
return c.State.BrotliCompressionLevel()
}
2 changes: 2 additions & 0 deletions precompiles/precompile.go
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ func Precompiles() map[addr]ArbosPrecompile {
ArbOwnerPublic := insert(MakePrecompile(templates.ArbOwnerPublicMetaData, &ArbOwnerPublic{Address: hex("6b")}))
ArbOwnerPublic.methodsByName["GetInfraFeeAccount"].arbosVersion = 5
ArbOwnerPublic.methodsByName["RectifyChainOwner"].arbosVersion = 11
ArbOwnerPublic.methodsByName["GetBrotliCompressionLevel"].arbosVersion = 12

ArbRetryableImpl := &ArbRetryableTx{Address: types.ArbRetryableTxAddress}
ArbRetryable := insert(MakePrecompile(templates.ArbRetryableTxMetaData, ArbRetryableImpl))
Expand Down Expand Up @@ -589,6 +590,7 @@ func Precompiles() map[addr]ArbosPrecompile {
ArbOwner.methodsByName["SetInfraFeeAccount"].arbosVersion = 5
ArbOwner.methodsByName["ReleaseL1PricerSurplusFunds"].arbosVersion = 10
ArbOwner.methodsByName["SetChainConfig"].arbosVersion = 11
ArbOwner.methodsByName["SetBrotliCompressionLevel"].arbosVersion = 12

insert(ownerOnly(ArbOwnerImpl.Address, ArbOwner, emitOwnerActs))
insert(debugOnly(MakePrecompile(templates.ArbDebugMetaData, &ArbDebug{Address: hex("ff")})))
Expand Down
2 changes: 1 addition & 1 deletion system_tests/fees_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ func TestSequencerPriceAdjustsFrom25Gwei(t *testing.T) {
func compressedTxSize(t *testing.T, tx *types.Transaction) uint64 {
txBin, err := tx.MarshalBinary()
Require(t, err)
compressed, err := arbcompress.CompressFast(txBin)
compressed, err := arbcompress.CompressLevel(txBin, 0)
Require(t, err)
return uint64(len(compressed))
}
2 changes: 1 addition & 1 deletion system_tests/state_fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ func FuzzStateTransition(f *testing.F) {
binary.BigEndian.PutUint64(seqBatch[32:40], uint64(len(delayedMessages)))
if compressSeqMsg {
seqBatch = append(seqBatch, arbstate.BrotliMessageHeaderByte)
seqMsgCompressed, err := arbcompress.CompressFast(seqMsg)
seqMsgCompressed, err := arbcompress.CompressLevel(seqMsg, 0)
if err != nil {
panic(fmt.Sprintf("failed to compress sequencer message: %v", err))
}
Expand Down

0 comments on commit 3a48bd8

Please sign in to comment.