Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shorten block time #62

Merged
merged 20 commits into from
Aug 20, 2024
Merged

Shorten block time #62

merged 20 commits into from
Aug 20, 2024

Conversation

ironbeer
Copy link
Collaborator

ハードフォーク

  • ブロック間隔を15秒から6秒に変更
  • エポック間隔を5760から14400に変更
  • EnvironmentとStakeManagerコントラクトをアップデート

バグ修正

  • スケジューラの乱数シードがオーバーフローする可能性があった

コード改善

  • Environmentコントラクトのオンチェーン取得を廃止

@ironbeer ironbeer requested a review from tak1827 August 14, 2024 08:05
@ironbeer
Copy link
Collaborator Author

ironbeer commented Aug 14, 2024

今回のハードフォークは2段構えになってます

1. Environment&StakeManagerのアップデート

これまで通りのブロック番号ベースのハードフォークです。

9999999: deploymentSet{deployments11}, // TODO

2. Environment.updateValue()の実行

こちらはエポック番号ベースのハードフォークです。

func (c *ChainConfig) OasysShortenedBlockTimeStartEpoch() *big.Int {
if c.Oasys == nil {
return nil
}
if c.ChainID.Cmp(OasysMainnetChainConfig.ChainID) == 0 {
return big.NewInt(999) // TODO
}
if c.ChainID.Cmp(OasysTestnetChainConfig.ChainID) == 0 {
return big.NewInt(999) // TODO
}
return big.NewInt(10)
}

以下の条件に合致するブロックで実行されます。

  1. CurrentEpoch + 1が新しい環境値のStartEpochに一致する
  2. 現在ブロックがエポックの真ん中である
    func (p *environmentValue) ShouldUpdate(newValue *environmentValue, number uint64) bool {
    if p.StartEpoch.Cmp(newValue.StartEpoch) == 0 {
    return false // skip if same value
    }
    if p.Epoch(number)+1 != newValue.StartEpoch.Uint64() {
    return false // skip if not the previous epoch
    }
    // check if it is in the middle of the previous epoch
    return (number - p.EpochStartBlock(number)) == p.EpochPeriod.Uint64()/2
    }

例えばStartEpochに10が指定されている場合は54720がフォーク実行ブロックになります。

contracts/oasys/deployments.go Outdated Show resolved Hide resolved
params/config.go Show resolved Hide resolved
@ironbeer ironbeer force-pushed the feat/mod-block-time branch from b4cbd97 to 81a49e9 Compare August 16, 2024 11:00
var seed int64
if env.Epoch(number) >= c.chainConfig.OasysShortenedBlockTimeStartEpoch().Uint64() {
// prevent overflow
seed = new(big.Int).Mod(seedHash.Big(), BigMaxInt64).Int64()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

コメントで「ブロックタイムを短くすることととは関係ないが、overflowするとわかったので、合わせて修正した」というような内容を添えてもらえますでしょうか?


// Add array values to storage.
func (a *array) add(storage map[common.Hash]common.Hash, rootSlot common.Hash) error {
storage[rootSlot] = common.BigToHash(big.NewInt(int64(len(*a))))
func (a *array) apply(cfg *params.ChainConfig, storage map[common.Hash]common.Hash, rootSlot common.Hash) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}

if t, ok := extract(val).(structvalue); ok {
return int64(len(t))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Storageサイズは32byteごとにPackされます。
単純に要素をカウントするだけだと正確ではないので、そのことをTODOに残しておいてください。

例えば、次のStructの場合

struct X {
  address a;  // 20 bytes
  bool b;     // 1 bytes
  uint256 c;  // 32 bytes
}

消費されるSlotは
(20 bytes + 1 bytes) + (32bytes) -> 2 slot
です。

Packされた場合、structvalue.applyのmemberSlotも変わってきます。

Copy link
Collaborator Author

@ironbeer ironbeer Aug 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

そもそもですがstorage.goは記述者がストレージレイアウトの仕様を理解していることを前提にしています。そうでないとテストコードが書けないからです。
例えばstructvalue等のデータ構造を使わなくとも全てベタ書き可能ですがそれではあまりにも読み辛いかつ面倒なので用意したにすぎません。

// このStructのストレージを表現したいとする
// X({ a: address(255), b: true, c: uint256(65535) });

// structvalueパターン
storage{
  "0x00": structvalue{
    "0x00000000000000000000000000000000000000ff000000000000000000000001",  
    "0x000000000000000000000000000000000000000000000000000000000000ffff",
  },
}

// ベタ書きパターン
storage{
  "0x00": "0x00000000000000000000000000000000000000ff000000000000000000000001",
  "0x01": "0x000000000000000000000000000000000000000000000000000000000000ffff",
  },
}

ストレージレイアウトの仕様を理解していないとこのような記述をしてしまう可能性がありますがそれは対象外かつテストコードで検知するべきです。

storage{
  "0x00": structvalue{
    "0x00000000000000000000000000000000000000ff000000000000000000000001",  
    "0x000000000000000000000000000000000000000000000000000000000000ffff",
  },
  "0x01": "0x...",  // X.cの値を上書きしてしまった
}

作りこんでスロット計算を完璧にする事は可能ですが現時点では不要だと思っています。

slot := 0
for _, val := range structvalue {
  switch val.(type) {
    case uint8:
    case uint16:
    case uint32:
    ....
  }
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

注意書きを追加しました

// `struct` type value.
// Assumes that each contained value is exactly one slot in length (32 bytes).
type structvalue []interface{}

@tak1827 tak1827 self-requested a review August 20, 2024 00:02
@ironbeer
Copy link
Collaborator Author

TODO:フォークエポックを決める

SHORT_BLOCK_TIME_FORK_EPOCH_MAINNET = 999 // TODO
SHORT_BLOCK_TIME_FORK_EPOCH_TESTNET = 999 // TODO

@ironbeer ironbeer merged commit e7b523a into oasysgames:main Aug 20, 2024
@ironbeer ironbeer deleted the feat/mod-block-time branch August 26, 2024 03:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants