diff --git a/Cargo.lock b/Cargo.lock index f50cd93960..844a2ceaf8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2777,6 +2777,27 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "fendermint_actor_activity_tracker" +version = "0.1.0" +dependencies = [ + "anyhow", + "cid", + "fil_actor_eam", + "fil_actors_evm_shared", + "fil_actors_runtime", + "frc42_dispatch", + "fvm_ipld_blockstore", + "fvm_ipld_encoding", + "fvm_shared", + "hex-literal 0.4.1", + "log", + "multihash 0.18.1", + "num-derive 0.3.3", + "num-traits", + "serde", +] + [[package]] name = "fendermint_actor_chainmetadata" version = "0.1.0" @@ -2816,6 +2837,26 @@ dependencies = [ "serde", ] +[[package]] +name = "fendermint_actor_gas_market" +version = "0.1.0" +dependencies = [ + "anyhow", + "cid", + "fil_actors_evm_shared", + "fil_actors_runtime", + "frc42_dispatch", + "fvm_ipld_blockstore", + "fvm_ipld_encoding", + "fvm_shared", + "hex-literal 0.4.1", + "log", + "multihash 0.18.1", + "num-derive 0.3.3", + "num-traits", + "serde", +] + [[package]] name = "fendermint_actors" version = "0.1.0" @@ -2841,6 +2882,7 @@ dependencies = [ "bytes", "cid", "fendermint_abci", + "fendermint_actor_gas_market", "fendermint_app_options", "fendermint_app_settings", "fendermint_crypto", @@ -2965,6 +3007,7 @@ dependencies = [ "bytes", "cid", "ethers", + "fendermint_actor_gas_market", "fendermint_crypto", "fendermint_rpc", "fendermint_testing", @@ -3303,8 +3346,10 @@ dependencies = [ "base64 0.21.7", "cid", "ethers", + "fendermint_actor_activity_tracker", "fendermint_actor_chainmetadata", "fendermint_actor_eam", + "fendermint_actor_gas_market", "fendermint_actors", "fendermint_crypto", "fendermint_eth_hardhat", @@ -3332,6 +3377,7 @@ dependencies = [ "ipc-observability", "ipc_actors_abis", "libipld", + "merkle-tree-rs", "multihash 0.18.1", "num-traits", "pin-project", diff --git a/Cargo.toml b/Cargo.toml index ccc3db09b4..5c74d67a11 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,8 @@ members = [ "fendermint/vm/*", "fendermint/actors", "fendermint/actors/chainmetadata", + "fendermint/actors/gas_market", + "fendermint/actors/activity-tracker", ] [workspace.package] @@ -217,6 +219,7 @@ fil_actor_eam = { git = "https://github.com/filecoin-project/builtin-actors", ta fil_actors_runtime = { git = "https://github.com/filecoin-project/builtin-actors", tag = "v12.0.0" } fendermint_actor_eam = { path = "./fendermint/actors/eam" } +fendermint_actor_activity_tracker= { path = "./fendermint/actors/activity-tracker" } cid = { version = "0.10.1", default-features = false, features = [ "serde-codec", diff --git a/contracts/.storage-layouts/GatewayActorModifiers.json b/contracts/.storage-layouts/GatewayActorModifiers.json index c1987575a4..b2f59a8944 100644 --- a/contracts/.storage-layouts/GatewayActorModifiers.json +++ b/contracts/.storage-layouts/GatewayActorModifiers.json @@ -1,12 +1,12 @@ { "storage": [ { - "astId": 11979, + "astId": 11959, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "s", "offset": 0, "slot": "0", - "type": "t_struct(GatewayActorStorage)11965_storage" + "type": "t_struct(GatewayActorStorage)11945_storage" } ], "types": { @@ -27,14 +27,14 @@ "label": "bytes32[]", "numberOfBytes": "32" }, - "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage": { - "base": "t_struct(IpcEnvelope)18702_storage", + "t_array(t_struct(IpcEnvelope)19408_storage)dyn_storage": { + "base": "t_struct(IpcEnvelope)19408_storage", "encoding": "dynamic_array", "label": "struct IpcEnvelope[]", "numberOfBytes": "32" }, - "t_array(t_struct(Validator)18966_storage)dyn_storage": { - "base": "t_struct(Validator)18966_storage", + "t_array(t_struct(Validator)19672_storage)dyn_storage": { + "base": "t_struct(Validator)19672_storage", "encoding": "dynamic_array", "label": "struct Validator[]", "numberOfBytes": "32" @@ -54,22 +54,22 @@ "label": "bytes", "numberOfBytes": "32" }, - "t_enum(IpcMsgKind)18679": { + "t_enum(IpcMsgKind)19385": { "encoding": "inplace", "label": "enum IpcMsgKind", "numberOfBytes": "1" }, - "t_enum(PermissionMode)18912": { + "t_enum(PermissionMode)19618": { "encoding": "inplace", "label": "enum PermissionMode", "numberOfBytes": "1" }, - "t_enum(QuorumObjKind)18748": { + "t_enum(QuorumObjKind)19454": { "encoding": "inplace", "label": "enum QuorumObjKind", "numberOfBytes": "1" }, - "t_enum(StakingOperation)18835": { + "t_enum(StakingOperation)19541": { "encoding": "inplace", "label": "enum StakingOperation", "numberOfBytes": "1" @@ -81,12 +81,12 @@ "numberOfBytes": "32", "value": "t_bytes_storage" }, - "t_mapping(t_address,t_struct(ValidatorInfo)18907_storage)": { + "t_mapping(t_address,t_struct(ValidatorInfo)19613_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ValidatorInfo)", "numberOfBytes": "32", - "value": "t_struct(ValidatorInfo)18907_storage" + "value": "t_struct(ValidatorInfo)19613_storage" }, "t_mapping(t_address,t_uint16)": { "encoding": "mapping", @@ -95,19 +95,19 @@ "numberOfBytes": "32", "value": "t_uint16" }, - "t_mapping(t_bytes32,t_struct(IpcEnvelope)18702_storage)": { + "t_mapping(t_bytes32,t_struct(IpcEnvelope)19408_storage)": { "encoding": "mapping", "key": "t_bytes32", "label": "mapping(bytes32 => struct IpcEnvelope)", "numberOfBytes": "32", - "value": "t_struct(IpcEnvelope)18702_storage" + "value": "t_struct(IpcEnvelope)19408_storage" }, - "t_mapping(t_bytes32,t_struct(Subnet)18829_storage)": { + "t_mapping(t_bytes32,t_struct(Subnet)19535_storage)": { "encoding": "mapping", "key": "t_bytes32", "label": "mapping(bytes32 => struct Subnet)", "numberOfBytes": "32", - "value": "t_struct(Subnet)18829_storage" + "value": "t_struct(Subnet)19535_storage" }, "t_mapping(t_bytes32,t_uint256)": { "encoding": "mapping", @@ -137,40 +137,40 @@ "numberOfBytes": "32", "value": "t_struct(AddressSet)3459_storage" }, - "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18654_storage)": { + "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)19331_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct BottomUpCheckpoint)", "numberOfBytes": "32", - "value": "t_struct(BottomUpCheckpoint)18654_storage" + "value": "t_struct(BottomUpCheckpoint)19331_storage" }, - "t_mapping(t_uint256,t_struct(BottomUpMsgBatch)18668_storage)": { + "t_mapping(t_uint256,t_struct(BottomUpMsgBatch)19374_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct BottomUpMsgBatch)", "numberOfBytes": "32", - "value": "t_struct(BottomUpMsgBatch)18668_storage" + "value": "t_struct(BottomUpMsgBatch)19374_storage" }, - "t_mapping(t_uint256,t_struct(ParentFinality)18634_storage)": { + "t_mapping(t_uint256,t_struct(ParentFinality)19311_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct ParentFinality)", "numberOfBytes": "32", - "value": "t_struct(ParentFinality)18634_storage" + "value": "t_struct(ParentFinality)19311_storage" }, - "t_mapping(t_uint256,t_struct(QuorumInfo)18765_storage)": { + "t_mapping(t_uint256,t_struct(QuorumInfo)19471_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct QuorumInfo)", "numberOfBytes": "32", - "value": "t_struct(QuorumInfo)18765_storage" + "value": "t_struct(QuorumInfo)19471_storage" }, - "t_mapping(t_uint64,t_struct(StakingChange)18844_storage)": { + "t_mapping(t_uint64,t_struct(StakingChange)19550_storage)": { "encoding": "mapping", "key": "t_uint64", "label": "mapping(uint64 => struct StakingChange)", "numberOfBytes": "32", - "value": "t_struct(StakingChange)18844_storage" + "value": "t_struct(StakingChange)19550_storage" }, "t_struct(AddressSet)3459_storage": { "encoding": "inplace", @@ -187,20 +187,20 @@ ], "numberOfBytes": "64" }, - "t_struct(BottomUpCheckpoint)18654_storage": { + "t_struct(BottomUpCheckpoint)19331_storage": { "encoding": "inplace", "label": "struct BottomUpCheckpoint", "members": [ { - "astId": 18639, + "astId": 19316, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "subnetID", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18814_storage" + "type": "t_struct(SubnetID)19520_storage" }, { - "astId": 18642, + "astId": 19319, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "blockHeight", "offset": 0, @@ -208,7 +208,7 @@ "type": "t_uint256" }, { - "astId": 18645, + "astId": 19322, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "blockHash", "offset": 0, @@ -216,7 +216,7 @@ "type": "t_bytes32" }, { - "astId": 18648, + "astId": 19325, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "nextConfigurationNumber", "offset": 0, @@ -224,30 +224,30 @@ "type": "t_uint64" }, { - "astId": 18653, + "astId": 19330, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "msgs", "offset": 0, "slot": "5", - "type": "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage" + "type": "t_array(t_struct(IpcEnvelope)19408_storage)dyn_storage" } ], "numberOfBytes": "192" }, - "t_struct(BottomUpMsgBatch)18668_storage": { + "t_struct(BottomUpMsgBatch)19374_storage": { "encoding": "inplace", "label": "struct BottomUpMsgBatch", "members": [ { - "astId": 18659, + "astId": 19365, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "subnetID", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18814_storage" + "type": "t_struct(SubnetID)19520_storage" }, { - "astId": 18662, + "astId": 19368, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "blockHeight", "offset": 0, @@ -255,12 +255,12 @@ "type": "t_uint256" }, { - "astId": 18667, + "astId": 19373, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "msgs", "offset": 0, "slot": "3", - "type": "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage" + "type": "t_array(t_struct(IpcEnvelope)19408_storage)dyn_storage" } ], "numberOfBytes": "128" @@ -280,12 +280,12 @@ ], "numberOfBytes": "64" }, - "t_struct(FvmAddress)18733_storage": { + "t_struct(FvmAddress)19439_storage": { "encoding": "inplace", "label": "struct FvmAddress", "members": [ { - "astId": 18730, + "astId": 19436, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "addrType", "offset": 0, @@ -293,7 +293,7 @@ "type": "t_uint8" }, { - "astId": 18732, + "astId": 19438, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "payload", "offset": 0, @@ -303,12 +303,12 @@ ], "numberOfBytes": "64" }, - "t_struct(GatewayActorStorage)11965_storage": { + "t_struct(GatewayActorStorage)11945_storage": { "encoding": "inplace", "label": "struct GatewayActorStorage", "members": [ { - "astId": 11877, + "astId": 11857, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "latestParentHeight", "offset": 0, @@ -316,7 +316,7 @@ "type": "t_uint256" }, { - "astId": 11880, + "astId": 11860, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "bottomUpCheckPeriod", "offset": 0, @@ -324,7 +324,7 @@ "type": "t_uint256" }, { - "astId": 11883, + "astId": 11863, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "bottomUpMsgBatchPeriod", "offset": 0, @@ -332,7 +332,7 @@ "type": "t_uint256" }, { - "astId": 11886, + "astId": 11866, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "bottomUpNonce", "offset": 0, @@ -340,7 +340,7 @@ "type": "t_uint64" }, { - "astId": 11889, + "astId": 11869, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "appliedTopDownNonce", "offset": 8, @@ -348,7 +348,7 @@ "type": "t_uint64" }, { - "astId": 11892, + "astId": 11872, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "totalSubnets", "offset": 16, @@ -356,7 +356,7 @@ "type": "t_uint64" }, { - "astId": 11895, + "astId": 11875, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "maxMsgsPerBottomUpBatch", "offset": 24, @@ -364,7 +364,7 @@ "type": "t_uint64" }, { - "astId": 11898, + "astId": 11878, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "majorityPercentage", "offset": 0, @@ -372,7 +372,7 @@ "type": "t_uint8" }, { - "astId": 11901, + "astId": 11881, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "commitSha", "offset": 0, @@ -380,7 +380,7 @@ "type": "t_bytes32" }, { - "astId": 11904, + "astId": 11884, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "maxTreeDepth", "offset": 0, @@ -388,7 +388,7 @@ "type": "t_uint8" }, { - "astId": 11907, + "astId": 11887, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "generalPurposeCrossMsg", "offset": 1, @@ -396,7 +396,7 @@ "type": "t_bool" }, { - "astId": 11910, + "astId": 11890, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "multiLevelCrossMsg", "offset": 2, @@ -404,87 +404,87 @@ "type": "t_bool" }, { - "astId": 11914, + "astId": 11894, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "currentMembership", "offset": 0, "slot": "7", - "type": "t_struct(Membership)18974_storage" + "type": "t_struct(Membership)19680_storage" }, { - "astId": 11918, + "astId": 11898, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "lastMembership", "offset": 0, "slot": "9", - "type": "t_struct(Membership)18974_storage" + "type": "t_struct(Membership)19680_storage" }, { - "astId": 11922, + "astId": 11902, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "checkpointQuorumMap", "offset": 0, "slot": "11", - "type": "t_struct(QuorumMap)18797_storage" + "type": "t_struct(QuorumMap)19503_storage" }, { - "astId": 11926, + "astId": 11906, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "networkName", "offset": 0, "slot": "18", - "type": "t_struct(SubnetID)18814_storage" + "type": "t_struct(SubnetID)19520_storage" }, { - "astId": 11930, + "astId": 11910, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "validatorsTracker", "offset": 0, "slot": "20", - "type": "t_struct(ParentValidatorsTracker)18950_storage" + "type": "t_struct(ParentValidatorsTracker)19656_storage" }, { - "astId": 11936, + "astId": 11916, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "subnets", "offset": 0, "slot": "31", - "type": "t_mapping(t_bytes32,t_struct(Subnet)18829_storage)" + "type": "t_mapping(t_bytes32,t_struct(Subnet)19535_storage)" }, { - "astId": 11942, + "astId": 11922, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "finalitiesMap", "offset": 0, "slot": "32", - "type": "t_mapping(t_uint256,t_struct(ParentFinality)18634_storage)" + "type": "t_mapping(t_uint256,t_struct(ParentFinality)19311_storage)" }, { - "astId": 11948, + "astId": 11928, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "postbox", "offset": 0, "slot": "33", - "type": "t_mapping(t_bytes32,t_struct(IpcEnvelope)18702_storage)" + "type": "t_mapping(t_bytes32,t_struct(IpcEnvelope)19408_storage)" }, { - "astId": 11954, + "astId": 11934, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "bottomUpCheckpoints", "offset": 0, "slot": "34", - "type": "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18654_storage)" + "type": "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)19331_storage)" }, { - "astId": 11960, + "astId": 11940, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "bottomUpMsgBatches", "offset": 0, "slot": "35", - "type": "t_mapping(t_uint256,t_struct(BottomUpMsgBatch)18668_storage)" + "type": "t_mapping(t_uint256,t_struct(BottomUpMsgBatch)19374_storage)" }, { - "astId": 11964, + "astId": 11944, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "subnetKeys", "offset": 0, @@ -494,59 +494,59 @@ ], "numberOfBytes": "1216" }, - "t_struct(IPCAddress)18958_storage": { + "t_struct(IPCAddress)19664_storage": { "encoding": "inplace", "label": "struct IPCAddress", "members": [ { - "astId": 18954, + "astId": 19660, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "subnetId", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18814_storage" + "type": "t_struct(SubnetID)19520_storage" }, { - "astId": 18957, + "astId": 19663, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "rawAddress", "offset": 0, "slot": "2", - "type": "t_struct(FvmAddress)18733_storage" + "type": "t_struct(FvmAddress)19439_storage" } ], "numberOfBytes": "128" }, - "t_struct(IpcEnvelope)18702_storage": { + "t_struct(IpcEnvelope)19408_storage": { "encoding": "inplace", "label": "struct IpcEnvelope", "members": [ { - "astId": 18684, + "astId": 19390, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "kind", "offset": 0, "slot": "0", - "type": "t_enum(IpcMsgKind)18679" + "type": "t_enum(IpcMsgKind)19385" }, { - "astId": 18688, + "astId": 19394, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "to", "offset": 0, "slot": "1", - "type": "t_struct(IPCAddress)18958_storage" + "type": "t_struct(IPCAddress)19664_storage" }, { - "astId": 18692, + "astId": 19398, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "from", "offset": 0, "slot": "5", - "type": "t_struct(IPCAddress)18958_storage" + "type": "t_struct(IPCAddress)19664_storage" }, { - "astId": 18695, + "astId": 19401, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "nonce", "offset": 0, @@ -554,7 +554,7 @@ "type": "t_uint64" }, { - "astId": 18698, + "astId": 19404, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "value", "offset": 0, @@ -562,7 +562,7 @@ "type": "t_uint256" }, { - "astId": 18701, + "astId": 19407, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "message", "offset": 0, @@ -572,35 +572,35 @@ ], "numberOfBytes": "384" }, - "t_struct(MaxPQ)17125_storage": { + "t_struct(MaxPQ)17052_storage": { "encoding": "inplace", "label": "struct MaxPQ", "members": [ { - "astId": 17124, + "astId": 17051, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "inner", "offset": 0, "slot": "0", - "type": "t_struct(PQ)18373_storage" + "type": "t_struct(PQ)18300_storage" } ], "numberOfBytes": "96" }, - "t_struct(Membership)18974_storage": { + "t_struct(Membership)19680_storage": { "encoding": "inplace", "label": "struct Membership", "members": [ { - "astId": 18971, + "astId": 19677, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "validators", "offset": 0, "slot": "0", - "type": "t_array(t_struct(Validator)18966_storage)dyn_storage" + "type": "t_array(t_struct(Validator)19672_storage)dyn_storage" }, { - "astId": 18973, + "astId": 19679, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "configurationNumber", "offset": 0, @@ -610,27 +610,27 @@ ], "numberOfBytes": "64" }, - "t_struct(MinPQ)17743_storage": { + "t_struct(MinPQ)17670_storage": { "encoding": "inplace", "label": "struct MinPQ", "members": [ { - "astId": 17742, + "astId": 17669, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "inner", "offset": 0, "slot": "0", - "type": "t_struct(PQ)18373_storage" + "type": "t_struct(PQ)18300_storage" } ], "numberOfBytes": "96" }, - "t_struct(PQ)18373_storage": { + "t_struct(PQ)18300_storage": { "encoding": "inplace", "label": "struct PQ", "members": [ { - "astId": 18362, + "astId": 18289, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "size", "offset": 0, @@ -638,7 +638,7 @@ "type": "t_uint16" }, { - "astId": 18367, + "astId": 18294, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "addressToPos", "offset": 0, @@ -646,7 +646,7 @@ "type": "t_mapping(t_address,t_uint16)" }, { - "astId": 18372, + "astId": 18299, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "posToAddress", "offset": 0, @@ -656,12 +656,12 @@ ], "numberOfBytes": "96" }, - "t_struct(ParentFinality)18634_storage": { + "t_struct(ParentFinality)19311_storage": { "encoding": "inplace", "label": "struct ParentFinality", "members": [ { - "astId": 18631, + "astId": 19308, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "height", "offset": 0, @@ -669,7 +669,7 @@ "type": "t_uint256" }, { - "astId": 18633, + "astId": 19310, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "blockHash", "offset": 0, @@ -679,35 +679,35 @@ ], "numberOfBytes": "64" }, - "t_struct(ParentValidatorsTracker)18950_storage": { + "t_struct(ParentValidatorsTracker)19656_storage": { "encoding": "inplace", "label": "struct ParentValidatorsTracker", "members": [ { - "astId": 18946, + "astId": 19652, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "validators", "offset": 0, "slot": "0", - "type": "t_struct(ValidatorSet)18942_storage" + "type": "t_struct(ValidatorSet)19648_storage" }, { - "astId": 18949, + "astId": 19655, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "changes", "offset": 0, "slot": "9", - "type": "t_struct(StakingChangeLog)18865_storage" + "type": "t_struct(StakingChangeLog)19571_storage" } ], "numberOfBytes": "352" }, - "t_struct(QuorumInfo)18765_storage": { + "t_struct(QuorumInfo)19471_storage": { "encoding": "inplace", "label": "struct QuorumInfo", "members": [ { - "astId": 18752, + "astId": 19458, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "hash", "offset": 0, @@ -715,7 +715,7 @@ "type": "t_bytes32" }, { - "astId": 18755, + "astId": 19461, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "rootHash", "offset": 0, @@ -723,7 +723,7 @@ "type": "t_bytes32" }, { - "astId": 18758, + "astId": 19464, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "threshold", "offset": 0, @@ -731,7 +731,7 @@ "type": "t_uint256" }, { - "astId": 18761, + "astId": 19467, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "currentWeight", "offset": 0, @@ -739,7 +739,7 @@ "type": "t_uint256" }, { - "astId": 18764, + "astId": 19470, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "reached", "offset": 0, @@ -749,20 +749,20 @@ ], "numberOfBytes": "160" }, - "t_struct(QuorumMap)18797_storage": { + "t_struct(QuorumMap)19503_storage": { "encoding": "inplace", "label": "struct QuorumMap", "members": [ { - "astId": 18770, + "astId": 19476, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "quorumObjKind", "offset": 0, "slot": "0", - "type": "t_enum(QuorumObjKind)18748" + "type": "t_enum(QuorumObjKind)19454" }, { - "astId": 18773, + "astId": 19479, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "retentionHeight", "offset": 0, @@ -770,15 +770,15 @@ "type": "t_uint256" }, { - "astId": 18779, + "astId": 19485, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "quorumInfo", "offset": 0, "slot": "2", - "type": "t_mapping(t_uint256,t_struct(QuorumInfo)18765_storage)" + "type": "t_mapping(t_uint256,t_struct(QuorumInfo)19471_storage)" }, { - "astId": 18783, + "astId": 19489, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "incompleteQuorums", "offset": 0, @@ -786,7 +786,7 @@ "type": "t_struct(UintSet)3616_storage" }, { - "astId": 18789, + "astId": 19495, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "quorumSignatureSenders", "offset": 0, @@ -794,7 +794,7 @@ "type": "t_mapping(t_uint256,t_struct(AddressSet)3459_storage)" }, { - "astId": 18796, + "astId": 19502, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "quorumSignatures", "offset": 0, @@ -827,20 +827,20 @@ ], "numberOfBytes": "64" }, - "t_struct(StakingChange)18844_storage": { + "t_struct(StakingChange)19550_storage": { "encoding": "inplace", "label": "struct StakingChange", "members": [ { - "astId": 18839, + "astId": 19545, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "op", "offset": 0, "slot": "0", - "type": "t_enum(StakingOperation)18835" + "type": "t_enum(StakingOperation)19541" }, { - "astId": 18841, + "astId": 19547, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "payload", "offset": 0, @@ -848,7 +848,7 @@ "type": "t_bytes_storage" }, { - "astId": 18843, + "astId": 19549, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "validator", "offset": 0, @@ -858,12 +858,12 @@ ], "numberOfBytes": "96" }, - "t_struct(StakingChangeLog)18865_storage": { + "t_struct(StakingChangeLog)19571_storage": { "encoding": "inplace", "label": "struct StakingChangeLog", "members": [ { - "astId": 18855, + "astId": 19561, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "nextConfigurationNumber", "offset": 0, @@ -871,7 +871,7 @@ "type": "t_uint64" }, { - "astId": 18858, + "astId": 19564, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "startConfigurationNumber", "offset": 8, @@ -879,22 +879,22 @@ "type": "t_uint64" }, { - "astId": 18864, + "astId": 19570, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "changes", "offset": 0, "slot": "1", - "type": "t_mapping(t_uint64,t_struct(StakingChange)18844_storage)" + "type": "t_mapping(t_uint64,t_struct(StakingChange)19550_storage)" } ], "numberOfBytes": "64" }, - "t_struct(Subnet)18829_storage": { + "t_struct(Subnet)19535_storage": { "encoding": "inplace", "label": "struct Subnet", "members": [ { - "astId": 18817, + "astId": 19523, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "stake", "offset": 0, @@ -902,7 +902,7 @@ "type": "t_uint256" }, { - "astId": 18819, + "astId": 19525, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "genesisEpoch", "offset": 0, @@ -910,7 +910,7 @@ "type": "t_uint256" }, { - "astId": 18821, + "astId": 19527, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "circSupply", "offset": 0, @@ -918,7 +918,7 @@ "type": "t_uint256" }, { - "astId": 18823, + "astId": 19529, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "topDownNonce", "offset": 0, @@ -926,7 +926,7 @@ "type": "t_uint64" }, { - "astId": 18825, + "astId": 19531, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "appliedBottomUpNonce", "offset": 8, @@ -934,22 +934,22 @@ "type": "t_uint64" }, { - "astId": 18828, + "astId": 19534, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "id", "offset": 0, "slot": "4", - "type": "t_struct(SubnetID)18814_storage" + "type": "t_struct(SubnetID)19520_storage" } ], "numberOfBytes": "192" }, - "t_struct(SubnetID)18814_storage": { + "t_struct(SubnetID)19520_storage": { "encoding": "inplace", "label": "struct SubnetID", "members": [ { - "astId": 18809, + "astId": 19515, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "root", "offset": 0, @@ -957,7 +957,7 @@ "type": "t_uint64" }, { - "astId": 18813, + "astId": 19519, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "route", "offset": 0, @@ -982,12 +982,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Validator)18966_storage": { + "t_struct(Validator)19672_storage": { "encoding": "inplace", "label": "struct Validator", "members": [ { - "astId": 18961, + "astId": 19667, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "weight", "offset": 0, @@ -995,7 +995,7 @@ "type": "t_uint256" }, { - "astId": 18963, + "astId": 19669, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "addr", "offset": 0, @@ -1003,7 +1003,7 @@ "type": "t_address" }, { - "astId": 18965, + "astId": 19671, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "metadata", "offset": 0, @@ -1013,12 +1013,12 @@ ], "numberOfBytes": "96" }, - "t_struct(ValidatorInfo)18907_storage": { + "t_struct(ValidatorInfo)19613_storage": { "encoding": "inplace", "label": "struct ValidatorInfo", "members": [ { - "astId": 18899, + "astId": 19605, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "federatedPower", "offset": 0, @@ -1026,7 +1026,7 @@ "type": "t_uint256" }, { - "astId": 18901, + "astId": 19607, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "confirmedCollateral", "offset": 0, @@ -1034,7 +1034,7 @@ "type": "t_uint256" }, { - "astId": 18903, + "astId": 19609, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "totalCollateral", "offset": 0, @@ -1042,7 +1042,7 @@ "type": "t_uint256" }, { - "astId": 18906, + "astId": 19612, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "metadata", "offset": 0, @@ -1052,20 +1052,20 @@ ], "numberOfBytes": "128" }, - "t_struct(ValidatorSet)18942_storage": { + "t_struct(ValidatorSet)19648_storage": { "encoding": "inplace", "label": "struct ValidatorSet", "members": [ { - "astId": 18921, + "astId": 19627, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "permissionMode", "offset": 0, "slot": "0", - "type": "t_enum(PermissionMode)18912" + "type": "t_enum(PermissionMode)19618" }, { - "astId": 18924, + "astId": 19630, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "activeLimit", "offset": 1, @@ -1073,7 +1073,7 @@ "type": "t_uint16" }, { - "astId": 18927, + "astId": 19633, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "totalConfirmedCollateral", "offset": 0, @@ -1081,28 +1081,28 @@ "type": "t_uint256" }, { - "astId": 18933, + "astId": 19639, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "validators", "offset": 0, "slot": "2", - "type": "t_mapping(t_address,t_struct(ValidatorInfo)18907_storage)" + "type": "t_mapping(t_address,t_struct(ValidatorInfo)19613_storage)" }, { - "astId": 18937, + "astId": 19643, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "activeValidators", "offset": 0, "slot": "3", - "type": "t_struct(MinPQ)17743_storage" + "type": "t_struct(MinPQ)17670_storage" }, { - "astId": 18941, + "astId": 19647, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "waitingValidators", "offset": 0, "slot": "6", - "type": "t_struct(MaxPQ)17125_storage" + "type": "t_struct(MaxPQ)17052_storage" } ], "numberOfBytes": "288" diff --git a/contracts/.storage-layouts/GatewayDiamond.json b/contracts/.storage-layouts/GatewayDiamond.json index 8d68e6165a..a40c2ec87b 100644 --- a/contracts/.storage-layouts/GatewayDiamond.json +++ b/contracts/.storage-layouts/GatewayDiamond.json @@ -6,7 +6,7 @@ "label": "s", "offset": 0, "slot": "0", - "type": "t_struct(GatewayActorStorage)11965_storage" + "type": "t_struct(GatewayActorStorage)11945_storage" } ], "types": { @@ -27,14 +27,14 @@ "label": "bytes32[]", "numberOfBytes": "32" }, - "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage": { - "base": "t_struct(IpcEnvelope)18702_storage", + "t_array(t_struct(IpcEnvelope)19408_storage)dyn_storage": { + "base": "t_struct(IpcEnvelope)19408_storage", "encoding": "dynamic_array", "label": "struct IpcEnvelope[]", "numberOfBytes": "32" }, - "t_array(t_struct(Validator)18966_storage)dyn_storage": { - "base": "t_struct(Validator)18966_storage", + "t_array(t_struct(Validator)19672_storage)dyn_storage": { + "base": "t_struct(Validator)19672_storage", "encoding": "dynamic_array", "label": "struct Validator[]", "numberOfBytes": "32" @@ -54,22 +54,22 @@ "label": "bytes", "numberOfBytes": "32" }, - "t_enum(IpcMsgKind)18679": { + "t_enum(IpcMsgKind)19385": { "encoding": "inplace", "label": "enum IpcMsgKind", "numberOfBytes": "1" }, - "t_enum(PermissionMode)18912": { + "t_enum(PermissionMode)19618": { "encoding": "inplace", "label": "enum PermissionMode", "numberOfBytes": "1" }, - "t_enum(QuorumObjKind)18748": { + "t_enum(QuorumObjKind)19454": { "encoding": "inplace", "label": "enum QuorumObjKind", "numberOfBytes": "1" }, - "t_enum(StakingOperation)18835": { + "t_enum(StakingOperation)19541": { "encoding": "inplace", "label": "enum StakingOperation", "numberOfBytes": "1" @@ -81,12 +81,12 @@ "numberOfBytes": "32", "value": "t_bytes_storage" }, - "t_mapping(t_address,t_struct(ValidatorInfo)18907_storage)": { + "t_mapping(t_address,t_struct(ValidatorInfo)19613_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ValidatorInfo)", "numberOfBytes": "32", - "value": "t_struct(ValidatorInfo)18907_storage" + "value": "t_struct(ValidatorInfo)19613_storage" }, "t_mapping(t_address,t_uint16)": { "encoding": "mapping", @@ -95,19 +95,19 @@ "numberOfBytes": "32", "value": "t_uint16" }, - "t_mapping(t_bytes32,t_struct(IpcEnvelope)18702_storage)": { + "t_mapping(t_bytes32,t_struct(IpcEnvelope)19408_storage)": { "encoding": "mapping", "key": "t_bytes32", "label": "mapping(bytes32 => struct IpcEnvelope)", "numberOfBytes": "32", - "value": "t_struct(IpcEnvelope)18702_storage" + "value": "t_struct(IpcEnvelope)19408_storage" }, - "t_mapping(t_bytes32,t_struct(Subnet)18829_storage)": { + "t_mapping(t_bytes32,t_struct(Subnet)19535_storage)": { "encoding": "mapping", "key": "t_bytes32", "label": "mapping(bytes32 => struct Subnet)", "numberOfBytes": "32", - "value": "t_struct(Subnet)18829_storage" + "value": "t_struct(Subnet)19535_storage" }, "t_mapping(t_bytes32,t_uint256)": { "encoding": "mapping", @@ -137,40 +137,40 @@ "numberOfBytes": "32", "value": "t_struct(AddressSet)3459_storage" }, - "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18654_storage)": { + "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)19331_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct BottomUpCheckpoint)", "numberOfBytes": "32", - "value": "t_struct(BottomUpCheckpoint)18654_storage" + "value": "t_struct(BottomUpCheckpoint)19331_storage" }, - "t_mapping(t_uint256,t_struct(BottomUpMsgBatch)18668_storage)": { + "t_mapping(t_uint256,t_struct(BottomUpMsgBatch)19374_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct BottomUpMsgBatch)", "numberOfBytes": "32", - "value": "t_struct(BottomUpMsgBatch)18668_storage" + "value": "t_struct(BottomUpMsgBatch)19374_storage" }, - "t_mapping(t_uint256,t_struct(ParentFinality)18634_storage)": { + "t_mapping(t_uint256,t_struct(ParentFinality)19311_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct ParentFinality)", "numberOfBytes": "32", - "value": "t_struct(ParentFinality)18634_storage" + "value": "t_struct(ParentFinality)19311_storage" }, - "t_mapping(t_uint256,t_struct(QuorumInfo)18765_storage)": { + "t_mapping(t_uint256,t_struct(QuorumInfo)19471_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct QuorumInfo)", "numberOfBytes": "32", - "value": "t_struct(QuorumInfo)18765_storage" + "value": "t_struct(QuorumInfo)19471_storage" }, - "t_mapping(t_uint64,t_struct(StakingChange)18844_storage)": { + "t_mapping(t_uint64,t_struct(StakingChange)19550_storage)": { "encoding": "mapping", "key": "t_uint64", "label": "mapping(uint64 => struct StakingChange)", "numberOfBytes": "32", - "value": "t_struct(StakingChange)18844_storage" + "value": "t_struct(StakingChange)19550_storage" }, "t_struct(AddressSet)3459_storage": { "encoding": "inplace", @@ -187,20 +187,20 @@ ], "numberOfBytes": "64" }, - "t_struct(BottomUpCheckpoint)18654_storage": { + "t_struct(BottomUpCheckpoint)19331_storage": { "encoding": "inplace", "label": "struct BottomUpCheckpoint", "members": [ { - "astId": 18639, + "astId": 19316, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "subnetID", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18814_storage" + "type": "t_struct(SubnetID)19520_storage" }, { - "astId": 18642, + "astId": 19319, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "blockHeight", "offset": 0, @@ -208,7 +208,7 @@ "type": "t_uint256" }, { - "astId": 18645, + "astId": 19322, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "blockHash", "offset": 0, @@ -216,7 +216,7 @@ "type": "t_bytes32" }, { - "astId": 18648, + "astId": 19325, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "nextConfigurationNumber", "offset": 0, @@ -224,30 +224,30 @@ "type": "t_uint64" }, { - "astId": 18653, + "astId": 19330, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "msgs", "offset": 0, "slot": "5", - "type": "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage" + "type": "t_array(t_struct(IpcEnvelope)19408_storage)dyn_storage" } ], "numberOfBytes": "192" }, - "t_struct(BottomUpMsgBatch)18668_storage": { + "t_struct(BottomUpMsgBatch)19374_storage": { "encoding": "inplace", "label": "struct BottomUpMsgBatch", "members": [ { - "astId": 18659, + "astId": 19365, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "subnetID", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18814_storage" + "type": "t_struct(SubnetID)19520_storage" }, { - "astId": 18662, + "astId": 19368, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "blockHeight", "offset": 0, @@ -255,12 +255,12 @@ "type": "t_uint256" }, { - "astId": 18667, + "astId": 19373, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "msgs", "offset": 0, "slot": "3", - "type": "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage" + "type": "t_array(t_struct(IpcEnvelope)19408_storage)dyn_storage" } ], "numberOfBytes": "128" @@ -280,12 +280,12 @@ ], "numberOfBytes": "64" }, - "t_struct(FvmAddress)18733_storage": { + "t_struct(FvmAddress)19439_storage": { "encoding": "inplace", "label": "struct FvmAddress", "members": [ { - "astId": 18730, + "astId": 19436, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "addrType", "offset": 0, @@ -293,7 +293,7 @@ "type": "t_uint8" }, { - "astId": 18732, + "astId": 19438, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "payload", "offset": 0, @@ -303,12 +303,12 @@ ], "numberOfBytes": "64" }, - "t_struct(GatewayActorStorage)11965_storage": { + "t_struct(GatewayActorStorage)11945_storage": { "encoding": "inplace", "label": "struct GatewayActorStorage", "members": [ { - "astId": 11877, + "astId": 11857, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "latestParentHeight", "offset": 0, @@ -316,7 +316,7 @@ "type": "t_uint256" }, { - "astId": 11880, + "astId": 11860, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "bottomUpCheckPeriod", "offset": 0, @@ -324,7 +324,7 @@ "type": "t_uint256" }, { - "astId": 11883, + "astId": 11863, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "bottomUpMsgBatchPeriod", "offset": 0, @@ -332,7 +332,7 @@ "type": "t_uint256" }, { - "astId": 11886, + "astId": 11866, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "bottomUpNonce", "offset": 0, @@ -340,7 +340,7 @@ "type": "t_uint64" }, { - "astId": 11889, + "astId": 11869, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "appliedTopDownNonce", "offset": 8, @@ -348,7 +348,7 @@ "type": "t_uint64" }, { - "astId": 11892, + "astId": 11872, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "totalSubnets", "offset": 16, @@ -356,7 +356,7 @@ "type": "t_uint64" }, { - "astId": 11895, + "astId": 11875, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "maxMsgsPerBottomUpBatch", "offset": 24, @@ -364,7 +364,7 @@ "type": "t_uint64" }, { - "astId": 11898, + "astId": 11878, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "majorityPercentage", "offset": 0, @@ -372,7 +372,7 @@ "type": "t_uint8" }, { - "astId": 11901, + "astId": 11881, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "commitSha", "offset": 0, @@ -380,7 +380,7 @@ "type": "t_bytes32" }, { - "astId": 11904, + "astId": 11884, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "maxTreeDepth", "offset": 0, @@ -388,7 +388,7 @@ "type": "t_uint8" }, { - "astId": 11907, + "astId": 11887, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "generalPurposeCrossMsg", "offset": 1, @@ -396,7 +396,7 @@ "type": "t_bool" }, { - "astId": 11910, + "astId": 11890, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "multiLevelCrossMsg", "offset": 2, @@ -404,87 +404,87 @@ "type": "t_bool" }, { - "astId": 11914, + "astId": 11894, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "currentMembership", "offset": 0, "slot": "7", - "type": "t_struct(Membership)18974_storage" + "type": "t_struct(Membership)19680_storage" }, { - "astId": 11918, + "astId": 11898, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "lastMembership", "offset": 0, "slot": "9", - "type": "t_struct(Membership)18974_storage" + "type": "t_struct(Membership)19680_storage" }, { - "astId": 11922, + "astId": 11902, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "checkpointQuorumMap", "offset": 0, "slot": "11", - "type": "t_struct(QuorumMap)18797_storage" + "type": "t_struct(QuorumMap)19503_storage" }, { - "astId": 11926, + "astId": 11906, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "networkName", "offset": 0, "slot": "18", - "type": "t_struct(SubnetID)18814_storage" + "type": "t_struct(SubnetID)19520_storage" }, { - "astId": 11930, + "astId": 11910, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "validatorsTracker", "offset": 0, "slot": "20", - "type": "t_struct(ParentValidatorsTracker)18950_storage" + "type": "t_struct(ParentValidatorsTracker)19656_storage" }, { - "astId": 11936, + "astId": 11916, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "subnets", "offset": 0, "slot": "31", - "type": "t_mapping(t_bytes32,t_struct(Subnet)18829_storage)" + "type": "t_mapping(t_bytes32,t_struct(Subnet)19535_storage)" }, { - "astId": 11942, + "astId": 11922, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "finalitiesMap", "offset": 0, "slot": "32", - "type": "t_mapping(t_uint256,t_struct(ParentFinality)18634_storage)" + "type": "t_mapping(t_uint256,t_struct(ParentFinality)19311_storage)" }, { - "astId": 11948, + "astId": 11928, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "postbox", "offset": 0, "slot": "33", - "type": "t_mapping(t_bytes32,t_struct(IpcEnvelope)18702_storage)" + "type": "t_mapping(t_bytes32,t_struct(IpcEnvelope)19408_storage)" }, { - "astId": 11954, + "astId": 11934, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "bottomUpCheckpoints", "offset": 0, "slot": "34", - "type": "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18654_storage)" + "type": "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)19331_storage)" }, { - "astId": 11960, + "astId": 11940, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "bottomUpMsgBatches", "offset": 0, "slot": "35", - "type": "t_mapping(t_uint256,t_struct(BottomUpMsgBatch)18668_storage)" + "type": "t_mapping(t_uint256,t_struct(BottomUpMsgBatch)19374_storage)" }, { - "astId": 11964, + "astId": 11944, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "subnetKeys", "offset": 0, @@ -494,59 +494,59 @@ ], "numberOfBytes": "1216" }, - "t_struct(IPCAddress)18958_storage": { + "t_struct(IPCAddress)19664_storage": { "encoding": "inplace", "label": "struct IPCAddress", "members": [ { - "astId": 18954, + "astId": 19660, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "subnetId", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18814_storage" + "type": "t_struct(SubnetID)19520_storage" }, { - "astId": 18957, + "astId": 19663, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "rawAddress", "offset": 0, "slot": "2", - "type": "t_struct(FvmAddress)18733_storage" + "type": "t_struct(FvmAddress)19439_storage" } ], "numberOfBytes": "128" }, - "t_struct(IpcEnvelope)18702_storage": { + "t_struct(IpcEnvelope)19408_storage": { "encoding": "inplace", "label": "struct IpcEnvelope", "members": [ { - "astId": 18684, + "astId": 19390, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "kind", "offset": 0, "slot": "0", - "type": "t_enum(IpcMsgKind)18679" + "type": "t_enum(IpcMsgKind)19385" }, { - "astId": 18688, + "astId": 19394, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "to", "offset": 0, "slot": "1", - "type": "t_struct(IPCAddress)18958_storage" + "type": "t_struct(IPCAddress)19664_storage" }, { - "astId": 18692, + "astId": 19398, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "from", "offset": 0, "slot": "5", - "type": "t_struct(IPCAddress)18958_storage" + "type": "t_struct(IPCAddress)19664_storage" }, { - "astId": 18695, + "astId": 19401, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "nonce", "offset": 0, @@ -554,7 +554,7 @@ "type": "t_uint64" }, { - "astId": 18698, + "astId": 19404, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "value", "offset": 0, @@ -562,7 +562,7 @@ "type": "t_uint256" }, { - "astId": 18701, + "astId": 19407, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "message", "offset": 0, @@ -572,35 +572,35 @@ ], "numberOfBytes": "384" }, - "t_struct(MaxPQ)17125_storage": { + "t_struct(MaxPQ)17052_storage": { "encoding": "inplace", "label": "struct MaxPQ", "members": [ { - "astId": 17124, + "astId": 17051, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "inner", "offset": 0, "slot": "0", - "type": "t_struct(PQ)18373_storage" + "type": "t_struct(PQ)18300_storage" } ], "numberOfBytes": "96" }, - "t_struct(Membership)18974_storage": { + "t_struct(Membership)19680_storage": { "encoding": "inplace", "label": "struct Membership", "members": [ { - "astId": 18971, + "astId": 19677, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "validators", "offset": 0, "slot": "0", - "type": "t_array(t_struct(Validator)18966_storage)dyn_storage" + "type": "t_array(t_struct(Validator)19672_storage)dyn_storage" }, { - "astId": 18973, + "astId": 19679, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "configurationNumber", "offset": 0, @@ -610,27 +610,27 @@ ], "numberOfBytes": "64" }, - "t_struct(MinPQ)17743_storage": { + "t_struct(MinPQ)17670_storage": { "encoding": "inplace", "label": "struct MinPQ", "members": [ { - "astId": 17742, + "astId": 17669, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "inner", "offset": 0, "slot": "0", - "type": "t_struct(PQ)18373_storage" + "type": "t_struct(PQ)18300_storage" } ], "numberOfBytes": "96" }, - "t_struct(PQ)18373_storage": { + "t_struct(PQ)18300_storage": { "encoding": "inplace", "label": "struct PQ", "members": [ { - "astId": 18362, + "astId": 18289, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "size", "offset": 0, @@ -638,7 +638,7 @@ "type": "t_uint16" }, { - "astId": 18367, + "astId": 18294, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "addressToPos", "offset": 0, @@ -646,7 +646,7 @@ "type": "t_mapping(t_address,t_uint16)" }, { - "astId": 18372, + "astId": 18299, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "posToAddress", "offset": 0, @@ -656,12 +656,12 @@ ], "numberOfBytes": "96" }, - "t_struct(ParentFinality)18634_storage": { + "t_struct(ParentFinality)19311_storage": { "encoding": "inplace", "label": "struct ParentFinality", "members": [ { - "astId": 18631, + "astId": 19308, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "height", "offset": 0, @@ -669,7 +669,7 @@ "type": "t_uint256" }, { - "astId": 18633, + "astId": 19310, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "blockHash", "offset": 0, @@ -679,35 +679,35 @@ ], "numberOfBytes": "64" }, - "t_struct(ParentValidatorsTracker)18950_storage": { + "t_struct(ParentValidatorsTracker)19656_storage": { "encoding": "inplace", "label": "struct ParentValidatorsTracker", "members": [ { - "astId": 18946, + "astId": 19652, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "validators", "offset": 0, "slot": "0", - "type": "t_struct(ValidatorSet)18942_storage" + "type": "t_struct(ValidatorSet)19648_storage" }, { - "astId": 18949, + "astId": 19655, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "changes", "offset": 0, "slot": "9", - "type": "t_struct(StakingChangeLog)18865_storage" + "type": "t_struct(StakingChangeLog)19571_storage" } ], "numberOfBytes": "352" }, - "t_struct(QuorumInfo)18765_storage": { + "t_struct(QuorumInfo)19471_storage": { "encoding": "inplace", "label": "struct QuorumInfo", "members": [ { - "astId": 18752, + "astId": 19458, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "hash", "offset": 0, @@ -715,7 +715,7 @@ "type": "t_bytes32" }, { - "astId": 18755, + "astId": 19461, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "rootHash", "offset": 0, @@ -723,7 +723,7 @@ "type": "t_bytes32" }, { - "astId": 18758, + "astId": 19464, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "threshold", "offset": 0, @@ -731,7 +731,7 @@ "type": "t_uint256" }, { - "astId": 18761, + "astId": 19467, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "currentWeight", "offset": 0, @@ -739,7 +739,7 @@ "type": "t_uint256" }, { - "astId": 18764, + "astId": 19470, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "reached", "offset": 0, @@ -749,20 +749,20 @@ ], "numberOfBytes": "160" }, - "t_struct(QuorumMap)18797_storage": { + "t_struct(QuorumMap)19503_storage": { "encoding": "inplace", "label": "struct QuorumMap", "members": [ { - "astId": 18770, + "astId": 19476, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "quorumObjKind", "offset": 0, "slot": "0", - "type": "t_enum(QuorumObjKind)18748" + "type": "t_enum(QuorumObjKind)19454" }, { - "astId": 18773, + "astId": 19479, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "retentionHeight", "offset": 0, @@ -770,15 +770,15 @@ "type": "t_uint256" }, { - "astId": 18779, + "astId": 19485, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "quorumInfo", "offset": 0, "slot": "2", - "type": "t_mapping(t_uint256,t_struct(QuorumInfo)18765_storage)" + "type": "t_mapping(t_uint256,t_struct(QuorumInfo)19471_storage)" }, { - "astId": 18783, + "astId": 19489, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "incompleteQuorums", "offset": 0, @@ -786,7 +786,7 @@ "type": "t_struct(UintSet)3616_storage" }, { - "astId": 18789, + "astId": 19495, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "quorumSignatureSenders", "offset": 0, @@ -794,7 +794,7 @@ "type": "t_mapping(t_uint256,t_struct(AddressSet)3459_storage)" }, { - "astId": 18796, + "astId": 19502, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "quorumSignatures", "offset": 0, @@ -827,20 +827,20 @@ ], "numberOfBytes": "64" }, - "t_struct(StakingChange)18844_storage": { + "t_struct(StakingChange)19550_storage": { "encoding": "inplace", "label": "struct StakingChange", "members": [ { - "astId": 18839, + "astId": 19545, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "op", "offset": 0, "slot": "0", - "type": "t_enum(StakingOperation)18835" + "type": "t_enum(StakingOperation)19541" }, { - "astId": 18841, + "astId": 19547, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "payload", "offset": 0, @@ -848,7 +848,7 @@ "type": "t_bytes_storage" }, { - "astId": 18843, + "astId": 19549, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "validator", "offset": 0, @@ -858,12 +858,12 @@ ], "numberOfBytes": "96" }, - "t_struct(StakingChangeLog)18865_storage": { + "t_struct(StakingChangeLog)19571_storage": { "encoding": "inplace", "label": "struct StakingChangeLog", "members": [ { - "astId": 18855, + "astId": 19561, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "nextConfigurationNumber", "offset": 0, @@ -871,7 +871,7 @@ "type": "t_uint64" }, { - "astId": 18858, + "astId": 19564, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "startConfigurationNumber", "offset": 8, @@ -879,22 +879,22 @@ "type": "t_uint64" }, { - "astId": 18864, + "astId": 19570, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "changes", "offset": 0, "slot": "1", - "type": "t_mapping(t_uint64,t_struct(StakingChange)18844_storage)" + "type": "t_mapping(t_uint64,t_struct(StakingChange)19550_storage)" } ], "numberOfBytes": "64" }, - "t_struct(Subnet)18829_storage": { + "t_struct(Subnet)19535_storage": { "encoding": "inplace", "label": "struct Subnet", "members": [ { - "astId": 18817, + "astId": 19523, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "stake", "offset": 0, @@ -902,7 +902,7 @@ "type": "t_uint256" }, { - "astId": 18819, + "astId": 19525, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "genesisEpoch", "offset": 0, @@ -910,7 +910,7 @@ "type": "t_uint256" }, { - "astId": 18821, + "astId": 19527, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "circSupply", "offset": 0, @@ -918,7 +918,7 @@ "type": "t_uint256" }, { - "astId": 18823, + "astId": 19529, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "topDownNonce", "offset": 0, @@ -926,7 +926,7 @@ "type": "t_uint64" }, { - "astId": 18825, + "astId": 19531, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "appliedBottomUpNonce", "offset": 8, @@ -934,22 +934,22 @@ "type": "t_uint64" }, { - "astId": 18828, + "astId": 19534, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "id", "offset": 0, "slot": "4", - "type": "t_struct(SubnetID)18814_storage" + "type": "t_struct(SubnetID)19520_storage" } ], "numberOfBytes": "192" }, - "t_struct(SubnetID)18814_storage": { + "t_struct(SubnetID)19520_storage": { "encoding": "inplace", "label": "struct SubnetID", "members": [ { - "astId": 18809, + "astId": 19515, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "root", "offset": 0, @@ -957,7 +957,7 @@ "type": "t_uint64" }, { - "astId": 18813, + "astId": 19519, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "route", "offset": 0, @@ -982,12 +982,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Validator)18966_storage": { + "t_struct(Validator)19672_storage": { "encoding": "inplace", "label": "struct Validator", "members": [ { - "astId": 18961, + "astId": 19667, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "weight", "offset": 0, @@ -995,7 +995,7 @@ "type": "t_uint256" }, { - "astId": 18963, + "astId": 19669, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "addr", "offset": 0, @@ -1003,7 +1003,7 @@ "type": "t_address" }, { - "astId": 18965, + "astId": 19671, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "metadata", "offset": 0, @@ -1013,12 +1013,12 @@ ], "numberOfBytes": "96" }, - "t_struct(ValidatorInfo)18907_storage": { + "t_struct(ValidatorInfo)19613_storage": { "encoding": "inplace", "label": "struct ValidatorInfo", "members": [ { - "astId": 18899, + "astId": 19605, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "federatedPower", "offset": 0, @@ -1026,7 +1026,7 @@ "type": "t_uint256" }, { - "astId": 18901, + "astId": 19607, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "confirmedCollateral", "offset": 0, @@ -1034,7 +1034,7 @@ "type": "t_uint256" }, { - "astId": 18903, + "astId": 19609, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "totalCollateral", "offset": 0, @@ -1042,7 +1042,7 @@ "type": "t_uint256" }, { - "astId": 18906, + "astId": 19612, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "metadata", "offset": 0, @@ -1052,20 +1052,20 @@ ], "numberOfBytes": "128" }, - "t_struct(ValidatorSet)18942_storage": { + "t_struct(ValidatorSet)19648_storage": { "encoding": "inplace", "label": "struct ValidatorSet", "members": [ { - "astId": 18921, + "astId": 19627, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "permissionMode", "offset": 0, "slot": "0", - "type": "t_enum(PermissionMode)18912" + "type": "t_enum(PermissionMode)19618" }, { - "astId": 18924, + "astId": 19630, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "activeLimit", "offset": 1, @@ -1073,7 +1073,7 @@ "type": "t_uint16" }, { - "astId": 18927, + "astId": 19633, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "totalConfirmedCollateral", "offset": 0, @@ -1081,28 +1081,28 @@ "type": "t_uint256" }, { - "astId": 18933, + "astId": 19639, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "validators", "offset": 0, "slot": "2", - "type": "t_mapping(t_address,t_struct(ValidatorInfo)18907_storage)" + "type": "t_mapping(t_address,t_struct(ValidatorInfo)19613_storage)" }, { - "astId": 18937, + "astId": 19643, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "activeValidators", "offset": 0, "slot": "3", - "type": "t_struct(MinPQ)17743_storage" + "type": "t_struct(MinPQ)17670_storage" }, { - "astId": 18941, + "astId": 19647, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "waitingValidators", "offset": 0, "slot": "6", - "type": "t_struct(MaxPQ)17125_storage" + "type": "t_struct(MaxPQ)17052_storage" } ], "numberOfBytes": "288" diff --git a/contracts/.storage-layouts/SubnetActorDiamond.json b/contracts/.storage-layouts/SubnetActorDiamond.json index 1a7511cd67..0d89b74926 100644 --- a/contracts/.storage-layouts/SubnetActorDiamond.json +++ b/contracts/.storage-layouts/SubnetActorDiamond.json @@ -6,7 +6,7 @@ "label": "s", "offset": 0, "slot": "0", - "type": "t_struct(SubnetActorStorage)16379_storage" + "type": "t_struct(SubnetActorStorage)16306_storage" } ], "types": { @@ -27,14 +27,14 @@ "label": "bytes32[]", "numberOfBytes": "32" }, - "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage": { - "base": "t_struct(IpcEnvelope)18702_storage", + "t_array(t_struct(IpcEnvelope)19408_storage)dyn_storage": { + "base": "t_struct(IpcEnvelope)19408_storage", "encoding": "dynamic_array", "label": "struct IpcEnvelope[]", "numberOfBytes": "32" }, - "t_array(t_struct(Validator)18966_storage)dyn_storage": { - "base": "t_struct(Validator)18966_storage", + "t_array(t_struct(Validator)19672_storage)dyn_storage": { + "base": "t_struct(Validator)19672_storage", "encoding": "dynamic_array", "label": "struct Validator[]", "numberOfBytes": "32" @@ -54,7 +54,7 @@ "label": "bytes", "numberOfBytes": "32" }, - "t_enum(AssetKind)18987": { + "t_enum(AssetKind)19693": { "encoding": "inplace", "label": "enum AssetKind", "numberOfBytes": "1" @@ -64,17 +64,17 @@ "label": "enum ConsensusType", "numberOfBytes": "1" }, - "t_enum(IpcMsgKind)18679": { + "t_enum(IpcMsgKind)19385": { "encoding": "inplace", "label": "enum IpcMsgKind", "numberOfBytes": "1" }, - "t_enum(PermissionMode)18912": { + "t_enum(PermissionMode)19618": { "encoding": "inplace", "label": "enum PermissionMode", "numberOfBytes": "1" }, - "t_enum(StakingOperation)18835": { + "t_enum(StakingOperation)19541": { "encoding": "inplace", "label": "enum StakingOperation", "numberOfBytes": "1" @@ -91,19 +91,19 @@ "numberOfBytes": "32", "value": "t_string_storage" }, - "t_mapping(t_address,t_struct(AddressStakingReleases)18884_storage)": { + "t_mapping(t_address,t_struct(AddressStakingReleases)19590_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct AddressStakingReleases)", "numberOfBytes": "32", - "value": "t_struct(AddressStakingReleases)18884_storage" + "value": "t_struct(AddressStakingReleases)19590_storage" }, - "t_mapping(t_address,t_struct(ValidatorInfo)18907_storage)": { + "t_mapping(t_address,t_struct(ValidatorInfo)19613_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ValidatorInfo)", "numberOfBytes": "32", - "value": "t_struct(ValidatorInfo)18907_storage" + "value": "t_struct(ValidatorInfo)19613_storage" }, "t_mapping(t_address,t_uint16)": { "encoding": "mapping", @@ -133,26 +133,26 @@ "numberOfBytes": "32", "value": "t_address" }, - "t_mapping(t_uint16,t_struct(StakingRelease)18873_storage)": { + "t_mapping(t_uint16,t_struct(StakingRelease)19579_storage)": { "encoding": "mapping", "key": "t_uint16", "label": "mapping(uint16 => struct StakingRelease)", "numberOfBytes": "32", - "value": "t_struct(StakingRelease)18873_storage" + "value": "t_struct(StakingRelease)19579_storage" }, - "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18654_storage)": { + "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)19331_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct BottomUpCheckpoint)", "numberOfBytes": "32", - "value": "t_struct(BottomUpCheckpoint)18654_storage" + "value": "t_struct(BottomUpCheckpoint)19331_storage" }, - "t_mapping(t_uint64,t_struct(StakingChange)18844_storage)": { + "t_mapping(t_uint64,t_struct(StakingChange)19550_storage)": { "encoding": "mapping", "key": "t_uint64", "label": "mapping(uint64 => struct StakingChange)", "numberOfBytes": "32", - "value": "t_struct(StakingChange)18844_storage" + "value": "t_struct(StakingChange)19550_storage" }, "t_string_storage": { "encoding": "bytes", @@ -174,12 +174,12 @@ ], "numberOfBytes": "64" }, - "t_struct(AddressStakingReleases)18884_storage": { + "t_struct(AddressStakingReleases)19590_storage": { "encoding": "inplace", "label": "struct AddressStakingReleases", "members": [ { - "astId": 18876, + "astId": 19582, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "length", "offset": 0, @@ -187,7 +187,7 @@ "type": "t_uint16" }, { - "astId": 18878, + "astId": 19584, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "startIdx", "offset": 2, @@ -195,30 +195,30 @@ "type": "t_uint16" }, { - "astId": 18883, + "astId": 19589, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "releases", "offset": 0, "slot": "1", - "type": "t_mapping(t_uint16,t_struct(StakingRelease)18873_storage)" + "type": "t_mapping(t_uint16,t_struct(StakingRelease)19579_storage)" } ], "numberOfBytes": "64" }, - "t_struct(Asset)18983_storage": { + "t_struct(Asset)19689_storage": { "encoding": "inplace", "label": "struct Asset", "members": [ { - "astId": 18979, + "astId": 19685, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "kind", "offset": 0, "slot": "0", - "type": "t_enum(AssetKind)18987" + "type": "t_enum(AssetKind)19693" }, { - "astId": 18982, + "astId": 19688, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "tokenAddress", "offset": 1, @@ -228,20 +228,20 @@ ], "numberOfBytes": "32" }, - "t_struct(BottomUpCheckpoint)18654_storage": { + "t_struct(BottomUpCheckpoint)19331_storage": { "encoding": "inplace", "label": "struct BottomUpCheckpoint", "members": [ { - "astId": 18639, + "astId": 19316, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "subnetID", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18814_storage" + "type": "t_struct(SubnetID)19520_storage" }, { - "astId": 18642, + "astId": 19319, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "blockHeight", "offset": 0, @@ -249,7 +249,7 @@ "type": "t_uint256" }, { - "astId": 18645, + "astId": 19322, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "blockHash", "offset": 0, @@ -257,7 +257,7 @@ "type": "t_bytes32" }, { - "astId": 18648, + "astId": 19325, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "nextConfigurationNumber", "offset": 0, @@ -265,22 +265,22 @@ "type": "t_uint64" }, { - "astId": 18653, + "astId": 19330, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "msgs", "offset": 0, "slot": "5", - "type": "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage" + "type": "t_array(t_struct(IpcEnvelope)19408_storage)dyn_storage" } ], "numberOfBytes": "192" }, - "t_struct(FvmAddress)18733_storage": { + "t_struct(FvmAddress)19439_storage": { "encoding": "inplace", "label": "struct FvmAddress", "members": [ { - "astId": 18730, + "astId": 19436, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "addrType", "offset": 0, @@ -288,7 +288,7 @@ "type": "t_uint8" }, { - "astId": 18732, + "astId": 19438, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "payload", "offset": 0, @@ -298,59 +298,59 @@ ], "numberOfBytes": "64" }, - "t_struct(IPCAddress)18958_storage": { + "t_struct(IPCAddress)19664_storage": { "encoding": "inplace", "label": "struct IPCAddress", "members": [ { - "astId": 18954, + "astId": 19660, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "subnetId", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18814_storage" + "type": "t_struct(SubnetID)19520_storage" }, { - "astId": 18957, + "astId": 19663, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "rawAddress", "offset": 0, "slot": "2", - "type": "t_struct(FvmAddress)18733_storage" + "type": "t_struct(FvmAddress)19439_storage" } ], "numberOfBytes": "128" }, - "t_struct(IpcEnvelope)18702_storage": { + "t_struct(IpcEnvelope)19408_storage": { "encoding": "inplace", "label": "struct IpcEnvelope", "members": [ { - "astId": 18684, + "astId": 19390, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "kind", "offset": 0, "slot": "0", - "type": "t_enum(IpcMsgKind)18679" + "type": "t_enum(IpcMsgKind)19385" }, { - "astId": 18688, + "astId": 19394, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "to", "offset": 0, "slot": "1", - "type": "t_struct(IPCAddress)18958_storage" + "type": "t_struct(IPCAddress)19664_storage" }, { - "astId": 18692, + "astId": 19398, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "from", "offset": 0, "slot": "5", - "type": "t_struct(IPCAddress)18958_storage" + "type": "t_struct(IPCAddress)19664_storage" }, { - "astId": 18695, + "astId": 19401, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "nonce", "offset": 0, @@ -358,7 +358,7 @@ "type": "t_uint64" }, { - "astId": 18698, + "astId": 19404, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "value", "offset": 0, @@ -366,7 +366,7 @@ "type": "t_uint256" }, { - "astId": 18701, + "astId": 19407, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "message", "offset": 0, @@ -376,42 +376,42 @@ ], "numberOfBytes": "384" }, - "t_struct(MaxPQ)17125_storage": { + "t_struct(MaxPQ)17052_storage": { "encoding": "inplace", "label": "struct MaxPQ", "members": [ { - "astId": 17124, + "astId": 17051, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "inner", "offset": 0, "slot": "0", - "type": "t_struct(PQ)18373_storage" + "type": "t_struct(PQ)18300_storage" } ], "numberOfBytes": "96" }, - "t_struct(MinPQ)17743_storage": { + "t_struct(MinPQ)17670_storage": { "encoding": "inplace", "label": "struct MinPQ", "members": [ { - "astId": 17742, + "astId": 17669, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "inner", "offset": 0, "slot": "0", - "type": "t_struct(PQ)18373_storage" + "type": "t_struct(PQ)18300_storage" } ], "numberOfBytes": "96" }, - "t_struct(PQ)18373_storage": { + "t_struct(PQ)18300_storage": { "encoding": "inplace", "label": "struct PQ", "members": [ { - "astId": 18362, + "astId": 18289, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "size", "offset": 0, @@ -419,7 +419,7 @@ "type": "t_uint16" }, { - "astId": 18367, + "astId": 18294, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "addressToPos", "offset": 0, @@ -427,7 +427,7 @@ "type": "t_mapping(t_address,t_uint16)" }, { - "astId": 18372, + "astId": 18299, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "posToAddress", "offset": 0, @@ -460,20 +460,20 @@ ], "numberOfBytes": "64" }, - "t_struct(StakingChange)18844_storage": { + "t_struct(StakingChange)19550_storage": { "encoding": "inplace", "label": "struct StakingChange", "members": [ { - "astId": 18839, + "astId": 19545, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "op", "offset": 0, "slot": "0", - "type": "t_enum(StakingOperation)18835" + "type": "t_enum(StakingOperation)19541" }, { - "astId": 18841, + "astId": 19547, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "payload", "offset": 0, @@ -481,7 +481,7 @@ "type": "t_bytes_storage" }, { - "astId": 18843, + "astId": 19549, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "validator", "offset": 0, @@ -491,12 +491,12 @@ ], "numberOfBytes": "96" }, - "t_struct(StakingChangeLog)18865_storage": { + "t_struct(StakingChangeLog)19571_storage": { "encoding": "inplace", "label": "struct StakingChangeLog", "members": [ { - "astId": 18855, + "astId": 19561, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "nextConfigurationNumber", "offset": 0, @@ -504,7 +504,7 @@ "type": "t_uint64" }, { - "astId": 18858, + "astId": 19564, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "startConfigurationNumber", "offset": 8, @@ -512,22 +512,22 @@ "type": "t_uint64" }, { - "astId": 18864, + "astId": 19570, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "changes", "offset": 0, "slot": "1", - "type": "t_mapping(t_uint64,t_struct(StakingChange)18844_storage)" + "type": "t_mapping(t_uint64,t_struct(StakingChange)19550_storage)" } ], "numberOfBytes": "64" }, - "t_struct(StakingRelease)18873_storage": { + "t_struct(StakingRelease)19579_storage": { "encoding": "inplace", "label": "struct StakingRelease", "members": [ { - "astId": 18869, + "astId": 19575, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "releaseAt", "offset": 0, @@ -535,7 +535,7 @@ "type": "t_uint256" }, { - "astId": 18872, + "astId": 19578, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "amount", "offset": 0, @@ -545,12 +545,12 @@ ], "numberOfBytes": "64" }, - "t_struct(StakingReleaseQueue)18895_storage": { + "t_struct(StakingReleaseQueue)19601_storage": { "encoding": "inplace", "label": "struct StakingReleaseQueue", "members": [ { - "astId": 18888, + "astId": 19594, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "lockingDuration", "offset": 0, @@ -558,22 +558,22 @@ "type": "t_uint256" }, { - "astId": 18894, + "astId": 19600, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "releases", "offset": 0, "slot": "1", - "type": "t_mapping(t_address,t_struct(AddressStakingReleases)18884_storage)" + "type": "t_mapping(t_address,t_struct(AddressStakingReleases)19590_storage)" } ], "numberOfBytes": "64" }, - "t_struct(SubnetActorStorage)16379_storage": { + "t_struct(SubnetActorStorage)16306_storage": { "encoding": "inplace", "label": "struct SubnetActorStorage", "members": [ { - "astId": 16286, + "astId": 16213, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "genesisCircSupply", "offset": 0, @@ -581,7 +581,7 @@ "type": "t_uint256" }, { - "astId": 16289, + "astId": 16216, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "lastBottomUpCheckpointHeight", "offset": 0, @@ -589,7 +589,7 @@ "type": "t_uint256" }, { - "astId": 16292, + "astId": 16219, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "minActivationCollateral", "offset": 0, @@ -597,7 +597,7 @@ "type": "t_uint256" }, { - "astId": 16295, + "astId": 16222, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "bottomUpCheckPeriod", "offset": 0, @@ -605,7 +605,7 @@ "type": "t_uint256" }, { - "astId": 16297, + "astId": 16224, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "currentSubnetHash", "offset": 0, @@ -613,7 +613,7 @@ "type": "t_bytes32" }, { - "astId": 16300, + "astId": 16227, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "ipcGatewayAddr", "offset": 0, @@ -621,7 +621,7 @@ "type": "t_address" }, { - "astId": 16303, + "astId": 16230, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "maxMsgsPerBottomUpBatch", "offset": 20, @@ -629,7 +629,7 @@ "type": "t_uint64" }, { - "astId": 16306, + "astId": 16233, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "majorityPercentage", "offset": 28, @@ -637,7 +637,7 @@ "type": "t_uint8" }, { - "astId": 16309, + "astId": 16236, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "powerScale", "offset": 29, @@ -645,7 +645,7 @@ "type": "t_int8" }, { - "astId": 16313, + "astId": 16240, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "consensus", "offset": 30, @@ -653,7 +653,7 @@ "type": "t_enum(ConsensusType)5500" }, { - "astId": 16316, + "astId": 16243, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "bootstrapped", "offset": 31, @@ -661,7 +661,7 @@ "type": "t_bool" }, { - "astId": 16319, + "astId": 16246, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "minValidators", "offset": 0, @@ -669,7 +669,7 @@ "type": "t_uint64" }, { - "astId": 16322, + "astId": 16249, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "killed", "offset": 8, @@ -677,55 +677,55 @@ "type": "t_bool" }, { - "astId": 16326, + "astId": 16253, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "supplySource", "offset": 0, "slot": "7", - "type": "t_struct(Asset)18983_storage" + "type": "t_struct(Asset)19689_storage" }, { - "astId": 16330, + "astId": 16257, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "collateralSource", "offset": 0, "slot": "8", - "type": "t_struct(Asset)18983_storage" + "type": "t_struct(Asset)19689_storage" }, { - "astId": 16334, + "astId": 16261, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "parentId", "offset": 0, "slot": "9", - "type": "t_struct(SubnetID)18814_storage" + "type": "t_struct(SubnetID)19520_storage" }, { - "astId": 16338, + "astId": 16265, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "validatorSet", "offset": 0, "slot": "11", - "type": "t_struct(ValidatorSet)18942_storage" + "type": "t_struct(ValidatorSet)19648_storage" }, { - "astId": 16342, + "astId": 16269, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "changeSet", "offset": 0, "slot": "20", - "type": "t_struct(StakingChangeLog)18865_storage" + "type": "t_struct(StakingChangeLog)19571_storage" }, { - "astId": 16346, + "astId": 16273, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "releaseQueue", "offset": 0, "slot": "22", - "type": "t_struct(StakingReleaseQueue)18895_storage" + "type": "t_struct(StakingReleaseQueue)19601_storage" }, { - "astId": 16351, + "astId": 16278, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "bootstrapNodes", "offset": 0, @@ -733,7 +733,7 @@ "type": "t_mapping(t_address,t_string_storage)" }, { - "astId": 16355, + "astId": 16282, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "bootstrapOwners", "offset": 0, @@ -741,23 +741,23 @@ "type": "t_struct(AddressSet)3459_storage" }, { - "astId": 16361, + "astId": 16288, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "committedCheckpoints", "offset": 0, "slot": "27", - "type": "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18654_storage)" + "type": "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)19331_storage)" }, { - "astId": 16366, + "astId": 16293, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "genesisValidators", "offset": 0, "slot": "28", - "type": "t_array(t_struct(Validator)18966_storage)dyn_storage" + "type": "t_array(t_struct(Validator)19672_storage)dyn_storage" }, { - "astId": 16371, + "astId": 16298, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "genesisBalance", "offset": 0, @@ -765,7 +765,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 16375, + "astId": 16302, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "genesisBalanceKeys", "offset": 0, @@ -773,7 +773,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 16378, + "astId": 16305, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "validatorGater", "offset": 0, @@ -783,12 +783,12 @@ ], "numberOfBytes": "1024" }, - "t_struct(SubnetID)18814_storage": { + "t_struct(SubnetID)19520_storage": { "encoding": "inplace", "label": "struct SubnetID", "members": [ { - "astId": 18809, + "astId": 19515, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "root", "offset": 0, @@ -796,7 +796,7 @@ "type": "t_uint64" }, { - "astId": 18813, + "astId": 19519, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "route", "offset": 0, @@ -806,12 +806,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Validator)18966_storage": { + "t_struct(Validator)19672_storage": { "encoding": "inplace", "label": "struct Validator", "members": [ { - "astId": 18961, + "astId": 19667, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "weight", "offset": 0, @@ -819,7 +819,7 @@ "type": "t_uint256" }, { - "astId": 18963, + "astId": 19669, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "addr", "offset": 0, @@ -827,7 +827,7 @@ "type": "t_address" }, { - "astId": 18965, + "astId": 19671, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "metadata", "offset": 0, @@ -837,12 +837,12 @@ ], "numberOfBytes": "96" }, - "t_struct(ValidatorInfo)18907_storage": { + "t_struct(ValidatorInfo)19613_storage": { "encoding": "inplace", "label": "struct ValidatorInfo", "members": [ { - "astId": 18899, + "astId": 19605, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "federatedPower", "offset": 0, @@ -850,7 +850,7 @@ "type": "t_uint256" }, { - "astId": 18901, + "astId": 19607, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "confirmedCollateral", "offset": 0, @@ -858,7 +858,7 @@ "type": "t_uint256" }, { - "astId": 18903, + "astId": 19609, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "totalCollateral", "offset": 0, @@ -866,7 +866,7 @@ "type": "t_uint256" }, { - "astId": 18906, + "astId": 19612, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "metadata", "offset": 0, @@ -876,20 +876,20 @@ ], "numberOfBytes": "128" }, - "t_struct(ValidatorSet)18942_storage": { + "t_struct(ValidatorSet)19648_storage": { "encoding": "inplace", "label": "struct ValidatorSet", "members": [ { - "astId": 18921, + "astId": 19627, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "permissionMode", "offset": 0, "slot": "0", - "type": "t_enum(PermissionMode)18912" + "type": "t_enum(PermissionMode)19618" }, { - "astId": 18924, + "astId": 19630, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "activeLimit", "offset": 1, @@ -897,7 +897,7 @@ "type": "t_uint16" }, { - "astId": 18927, + "astId": 19633, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "totalConfirmedCollateral", "offset": 0, @@ -905,28 +905,28 @@ "type": "t_uint256" }, { - "astId": 18933, + "astId": 19639, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "validators", "offset": 0, "slot": "2", - "type": "t_mapping(t_address,t_struct(ValidatorInfo)18907_storage)" + "type": "t_mapping(t_address,t_struct(ValidatorInfo)19613_storage)" }, { - "astId": 18937, + "astId": 19643, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "activeValidators", "offset": 0, "slot": "3", - "type": "t_struct(MinPQ)17743_storage" + "type": "t_struct(MinPQ)17670_storage" }, { - "astId": 18941, + "astId": 19647, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "waitingValidators", "offset": 0, "slot": "6", - "type": "t_struct(MaxPQ)17125_storage" + "type": "t_struct(MaxPQ)17052_storage" } ], "numberOfBytes": "288" diff --git a/contracts/.storage-layouts/SubnetActorModifiers.json b/contracts/.storage-layouts/SubnetActorModifiers.json index dee7289072..baf89be370 100644 --- a/contracts/.storage-layouts/SubnetActorModifiers.json +++ b/contracts/.storage-layouts/SubnetActorModifiers.json @@ -1,12 +1,12 @@ { "storage": [ { - "astId": 16393, + "astId": 16320, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "s", "offset": 0, "slot": "0", - "type": "t_struct(SubnetActorStorage)16379_storage" + "type": "t_struct(SubnetActorStorage)16306_storage" } ], "types": { @@ -27,14 +27,14 @@ "label": "bytes32[]", "numberOfBytes": "32" }, - "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage": { - "base": "t_struct(IpcEnvelope)18702_storage", + "t_array(t_struct(IpcEnvelope)19408_storage)dyn_storage": { + "base": "t_struct(IpcEnvelope)19408_storage", "encoding": "dynamic_array", "label": "struct IpcEnvelope[]", "numberOfBytes": "32" }, - "t_array(t_struct(Validator)18966_storage)dyn_storage": { - "base": "t_struct(Validator)18966_storage", + "t_array(t_struct(Validator)19672_storage)dyn_storage": { + "base": "t_struct(Validator)19672_storage", "encoding": "dynamic_array", "label": "struct Validator[]", "numberOfBytes": "32" @@ -54,7 +54,7 @@ "label": "bytes", "numberOfBytes": "32" }, - "t_enum(AssetKind)18987": { + "t_enum(AssetKind)19693": { "encoding": "inplace", "label": "enum AssetKind", "numberOfBytes": "1" @@ -64,17 +64,17 @@ "label": "enum ConsensusType", "numberOfBytes": "1" }, - "t_enum(IpcMsgKind)18679": { + "t_enum(IpcMsgKind)19385": { "encoding": "inplace", "label": "enum IpcMsgKind", "numberOfBytes": "1" }, - "t_enum(PermissionMode)18912": { + "t_enum(PermissionMode)19618": { "encoding": "inplace", "label": "enum PermissionMode", "numberOfBytes": "1" }, - "t_enum(StakingOperation)18835": { + "t_enum(StakingOperation)19541": { "encoding": "inplace", "label": "enum StakingOperation", "numberOfBytes": "1" @@ -91,19 +91,19 @@ "numberOfBytes": "32", "value": "t_string_storage" }, - "t_mapping(t_address,t_struct(AddressStakingReleases)18884_storage)": { + "t_mapping(t_address,t_struct(AddressStakingReleases)19590_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct AddressStakingReleases)", "numberOfBytes": "32", - "value": "t_struct(AddressStakingReleases)18884_storage" + "value": "t_struct(AddressStakingReleases)19590_storage" }, - "t_mapping(t_address,t_struct(ValidatorInfo)18907_storage)": { + "t_mapping(t_address,t_struct(ValidatorInfo)19613_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ValidatorInfo)", "numberOfBytes": "32", - "value": "t_struct(ValidatorInfo)18907_storage" + "value": "t_struct(ValidatorInfo)19613_storage" }, "t_mapping(t_address,t_uint16)": { "encoding": "mapping", @@ -133,26 +133,26 @@ "numberOfBytes": "32", "value": "t_address" }, - "t_mapping(t_uint16,t_struct(StakingRelease)18873_storage)": { + "t_mapping(t_uint16,t_struct(StakingRelease)19579_storage)": { "encoding": "mapping", "key": "t_uint16", "label": "mapping(uint16 => struct StakingRelease)", "numberOfBytes": "32", - "value": "t_struct(StakingRelease)18873_storage" + "value": "t_struct(StakingRelease)19579_storage" }, - "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18654_storage)": { + "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)19331_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct BottomUpCheckpoint)", "numberOfBytes": "32", - "value": "t_struct(BottomUpCheckpoint)18654_storage" + "value": "t_struct(BottomUpCheckpoint)19331_storage" }, - "t_mapping(t_uint64,t_struct(StakingChange)18844_storage)": { + "t_mapping(t_uint64,t_struct(StakingChange)19550_storage)": { "encoding": "mapping", "key": "t_uint64", "label": "mapping(uint64 => struct StakingChange)", "numberOfBytes": "32", - "value": "t_struct(StakingChange)18844_storage" + "value": "t_struct(StakingChange)19550_storage" }, "t_string_storage": { "encoding": "bytes", @@ -174,12 +174,12 @@ ], "numberOfBytes": "64" }, - "t_struct(AddressStakingReleases)18884_storage": { + "t_struct(AddressStakingReleases)19590_storage": { "encoding": "inplace", "label": "struct AddressStakingReleases", "members": [ { - "astId": 18876, + "astId": 19582, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "length", "offset": 0, @@ -187,7 +187,7 @@ "type": "t_uint16" }, { - "astId": 18878, + "astId": 19584, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "startIdx", "offset": 2, @@ -195,30 +195,30 @@ "type": "t_uint16" }, { - "astId": 18883, + "astId": 19589, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "releases", "offset": 0, "slot": "1", - "type": "t_mapping(t_uint16,t_struct(StakingRelease)18873_storage)" + "type": "t_mapping(t_uint16,t_struct(StakingRelease)19579_storage)" } ], "numberOfBytes": "64" }, - "t_struct(Asset)18983_storage": { + "t_struct(Asset)19689_storage": { "encoding": "inplace", "label": "struct Asset", "members": [ { - "astId": 18979, + "astId": 19685, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "kind", "offset": 0, "slot": "0", - "type": "t_enum(AssetKind)18987" + "type": "t_enum(AssetKind)19693" }, { - "astId": 18982, + "astId": 19688, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "tokenAddress", "offset": 1, @@ -228,20 +228,20 @@ ], "numberOfBytes": "32" }, - "t_struct(BottomUpCheckpoint)18654_storage": { + "t_struct(BottomUpCheckpoint)19331_storage": { "encoding": "inplace", "label": "struct BottomUpCheckpoint", "members": [ { - "astId": 18639, + "astId": 19316, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "subnetID", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18814_storage" + "type": "t_struct(SubnetID)19520_storage" }, { - "astId": 18642, + "astId": 19319, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "blockHeight", "offset": 0, @@ -249,7 +249,7 @@ "type": "t_uint256" }, { - "astId": 18645, + "astId": 19322, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "blockHash", "offset": 0, @@ -257,7 +257,7 @@ "type": "t_bytes32" }, { - "astId": 18648, + "astId": 19325, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "nextConfigurationNumber", "offset": 0, @@ -265,22 +265,22 @@ "type": "t_uint64" }, { - "astId": 18653, + "astId": 19330, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "msgs", "offset": 0, "slot": "5", - "type": "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage" + "type": "t_array(t_struct(IpcEnvelope)19408_storage)dyn_storage" } ], "numberOfBytes": "192" }, - "t_struct(FvmAddress)18733_storage": { + "t_struct(FvmAddress)19439_storage": { "encoding": "inplace", "label": "struct FvmAddress", "members": [ { - "astId": 18730, + "astId": 19436, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "addrType", "offset": 0, @@ -288,7 +288,7 @@ "type": "t_uint8" }, { - "astId": 18732, + "astId": 19438, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "payload", "offset": 0, @@ -298,59 +298,59 @@ ], "numberOfBytes": "64" }, - "t_struct(IPCAddress)18958_storage": { + "t_struct(IPCAddress)19664_storage": { "encoding": "inplace", "label": "struct IPCAddress", "members": [ { - "astId": 18954, + "astId": 19660, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "subnetId", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18814_storage" + "type": "t_struct(SubnetID)19520_storage" }, { - "astId": 18957, + "astId": 19663, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "rawAddress", "offset": 0, "slot": "2", - "type": "t_struct(FvmAddress)18733_storage" + "type": "t_struct(FvmAddress)19439_storage" } ], "numberOfBytes": "128" }, - "t_struct(IpcEnvelope)18702_storage": { + "t_struct(IpcEnvelope)19408_storage": { "encoding": "inplace", "label": "struct IpcEnvelope", "members": [ { - "astId": 18684, + "astId": 19390, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "kind", "offset": 0, "slot": "0", - "type": "t_enum(IpcMsgKind)18679" + "type": "t_enum(IpcMsgKind)19385" }, { - "astId": 18688, + "astId": 19394, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "to", "offset": 0, "slot": "1", - "type": "t_struct(IPCAddress)18958_storage" + "type": "t_struct(IPCAddress)19664_storage" }, { - "astId": 18692, + "astId": 19398, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "from", "offset": 0, "slot": "5", - "type": "t_struct(IPCAddress)18958_storage" + "type": "t_struct(IPCAddress)19664_storage" }, { - "astId": 18695, + "astId": 19401, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "nonce", "offset": 0, @@ -358,7 +358,7 @@ "type": "t_uint64" }, { - "astId": 18698, + "astId": 19404, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "value", "offset": 0, @@ -366,7 +366,7 @@ "type": "t_uint256" }, { - "astId": 18701, + "astId": 19407, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "message", "offset": 0, @@ -376,42 +376,42 @@ ], "numberOfBytes": "384" }, - "t_struct(MaxPQ)17125_storage": { + "t_struct(MaxPQ)17052_storage": { "encoding": "inplace", "label": "struct MaxPQ", "members": [ { - "astId": 17124, + "astId": 17051, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "inner", "offset": 0, "slot": "0", - "type": "t_struct(PQ)18373_storage" + "type": "t_struct(PQ)18300_storage" } ], "numberOfBytes": "96" }, - "t_struct(MinPQ)17743_storage": { + "t_struct(MinPQ)17670_storage": { "encoding": "inplace", "label": "struct MinPQ", "members": [ { - "astId": 17742, + "astId": 17669, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "inner", "offset": 0, "slot": "0", - "type": "t_struct(PQ)18373_storage" + "type": "t_struct(PQ)18300_storage" } ], "numberOfBytes": "96" }, - "t_struct(PQ)18373_storage": { + "t_struct(PQ)18300_storage": { "encoding": "inplace", "label": "struct PQ", "members": [ { - "astId": 18362, + "astId": 18289, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "size", "offset": 0, @@ -419,7 +419,7 @@ "type": "t_uint16" }, { - "astId": 18367, + "astId": 18294, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "addressToPos", "offset": 0, @@ -427,7 +427,7 @@ "type": "t_mapping(t_address,t_uint16)" }, { - "astId": 18372, + "astId": 18299, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "posToAddress", "offset": 0, @@ -460,20 +460,20 @@ ], "numberOfBytes": "64" }, - "t_struct(StakingChange)18844_storage": { + "t_struct(StakingChange)19550_storage": { "encoding": "inplace", "label": "struct StakingChange", "members": [ { - "astId": 18839, + "astId": 19545, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "op", "offset": 0, "slot": "0", - "type": "t_enum(StakingOperation)18835" + "type": "t_enum(StakingOperation)19541" }, { - "astId": 18841, + "astId": 19547, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "payload", "offset": 0, @@ -481,7 +481,7 @@ "type": "t_bytes_storage" }, { - "astId": 18843, + "astId": 19549, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "validator", "offset": 0, @@ -491,12 +491,12 @@ ], "numberOfBytes": "96" }, - "t_struct(StakingChangeLog)18865_storage": { + "t_struct(StakingChangeLog)19571_storage": { "encoding": "inplace", "label": "struct StakingChangeLog", "members": [ { - "astId": 18855, + "astId": 19561, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "nextConfigurationNumber", "offset": 0, @@ -504,7 +504,7 @@ "type": "t_uint64" }, { - "astId": 18858, + "astId": 19564, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "startConfigurationNumber", "offset": 8, @@ -512,22 +512,22 @@ "type": "t_uint64" }, { - "astId": 18864, + "astId": 19570, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "changes", "offset": 0, "slot": "1", - "type": "t_mapping(t_uint64,t_struct(StakingChange)18844_storage)" + "type": "t_mapping(t_uint64,t_struct(StakingChange)19550_storage)" } ], "numberOfBytes": "64" }, - "t_struct(StakingRelease)18873_storage": { + "t_struct(StakingRelease)19579_storage": { "encoding": "inplace", "label": "struct StakingRelease", "members": [ { - "astId": 18869, + "astId": 19575, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "releaseAt", "offset": 0, @@ -535,7 +535,7 @@ "type": "t_uint256" }, { - "astId": 18872, + "astId": 19578, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "amount", "offset": 0, @@ -545,12 +545,12 @@ ], "numberOfBytes": "64" }, - "t_struct(StakingReleaseQueue)18895_storage": { + "t_struct(StakingReleaseQueue)19601_storage": { "encoding": "inplace", "label": "struct StakingReleaseQueue", "members": [ { - "astId": 18888, + "astId": 19594, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "lockingDuration", "offset": 0, @@ -558,22 +558,22 @@ "type": "t_uint256" }, { - "astId": 18894, + "astId": 19600, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "releases", "offset": 0, "slot": "1", - "type": "t_mapping(t_address,t_struct(AddressStakingReleases)18884_storage)" + "type": "t_mapping(t_address,t_struct(AddressStakingReleases)19590_storage)" } ], "numberOfBytes": "64" }, - "t_struct(SubnetActorStorage)16379_storage": { + "t_struct(SubnetActorStorage)16306_storage": { "encoding": "inplace", "label": "struct SubnetActorStorage", "members": [ { - "astId": 16286, + "astId": 16213, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "genesisCircSupply", "offset": 0, @@ -581,7 +581,7 @@ "type": "t_uint256" }, { - "astId": 16289, + "astId": 16216, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "lastBottomUpCheckpointHeight", "offset": 0, @@ -589,7 +589,7 @@ "type": "t_uint256" }, { - "astId": 16292, + "astId": 16219, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "minActivationCollateral", "offset": 0, @@ -597,7 +597,7 @@ "type": "t_uint256" }, { - "astId": 16295, + "astId": 16222, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "bottomUpCheckPeriod", "offset": 0, @@ -605,7 +605,7 @@ "type": "t_uint256" }, { - "astId": 16297, + "astId": 16224, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "currentSubnetHash", "offset": 0, @@ -613,7 +613,7 @@ "type": "t_bytes32" }, { - "astId": 16300, + "astId": 16227, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "ipcGatewayAddr", "offset": 0, @@ -621,7 +621,7 @@ "type": "t_address" }, { - "astId": 16303, + "astId": 16230, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "maxMsgsPerBottomUpBatch", "offset": 20, @@ -629,7 +629,7 @@ "type": "t_uint64" }, { - "astId": 16306, + "astId": 16233, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "majorityPercentage", "offset": 28, @@ -637,7 +637,7 @@ "type": "t_uint8" }, { - "astId": 16309, + "astId": 16236, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "powerScale", "offset": 29, @@ -645,7 +645,7 @@ "type": "t_int8" }, { - "astId": 16313, + "astId": 16240, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "consensus", "offset": 30, @@ -653,7 +653,7 @@ "type": "t_enum(ConsensusType)5500" }, { - "astId": 16316, + "astId": 16243, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "bootstrapped", "offset": 31, @@ -661,7 +661,7 @@ "type": "t_bool" }, { - "astId": 16319, + "astId": 16246, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "minValidators", "offset": 0, @@ -669,7 +669,7 @@ "type": "t_uint64" }, { - "astId": 16322, + "astId": 16249, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "killed", "offset": 8, @@ -677,55 +677,55 @@ "type": "t_bool" }, { - "astId": 16326, + "astId": 16253, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "supplySource", "offset": 0, "slot": "7", - "type": "t_struct(Asset)18983_storage" + "type": "t_struct(Asset)19689_storage" }, { - "astId": 16330, + "astId": 16257, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "collateralSource", "offset": 0, "slot": "8", - "type": "t_struct(Asset)18983_storage" + "type": "t_struct(Asset)19689_storage" }, { - "astId": 16334, + "astId": 16261, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "parentId", "offset": 0, "slot": "9", - "type": "t_struct(SubnetID)18814_storage" + "type": "t_struct(SubnetID)19520_storage" }, { - "astId": 16338, + "astId": 16265, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "validatorSet", "offset": 0, "slot": "11", - "type": "t_struct(ValidatorSet)18942_storage" + "type": "t_struct(ValidatorSet)19648_storage" }, { - "astId": 16342, + "astId": 16269, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "changeSet", "offset": 0, "slot": "20", - "type": "t_struct(StakingChangeLog)18865_storage" + "type": "t_struct(StakingChangeLog)19571_storage" }, { - "astId": 16346, + "astId": 16273, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "releaseQueue", "offset": 0, "slot": "22", - "type": "t_struct(StakingReleaseQueue)18895_storage" + "type": "t_struct(StakingReleaseQueue)19601_storage" }, { - "astId": 16351, + "astId": 16278, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "bootstrapNodes", "offset": 0, @@ -733,7 +733,7 @@ "type": "t_mapping(t_address,t_string_storage)" }, { - "astId": 16355, + "astId": 16282, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "bootstrapOwners", "offset": 0, @@ -741,23 +741,23 @@ "type": "t_struct(AddressSet)3459_storage" }, { - "astId": 16361, + "astId": 16288, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "committedCheckpoints", "offset": 0, "slot": "27", - "type": "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18654_storage)" + "type": "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)19331_storage)" }, { - "astId": 16366, + "astId": 16293, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "genesisValidators", "offset": 0, "slot": "28", - "type": "t_array(t_struct(Validator)18966_storage)dyn_storage" + "type": "t_array(t_struct(Validator)19672_storage)dyn_storage" }, { - "astId": 16371, + "astId": 16298, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "genesisBalance", "offset": 0, @@ -765,7 +765,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 16375, + "astId": 16302, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "genesisBalanceKeys", "offset": 0, @@ -773,7 +773,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 16378, + "astId": 16305, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "validatorGater", "offset": 0, @@ -783,12 +783,12 @@ ], "numberOfBytes": "1024" }, - "t_struct(SubnetID)18814_storage": { + "t_struct(SubnetID)19520_storage": { "encoding": "inplace", "label": "struct SubnetID", "members": [ { - "astId": 18809, + "astId": 19515, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "root", "offset": 0, @@ -796,7 +796,7 @@ "type": "t_uint64" }, { - "astId": 18813, + "astId": 19519, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "route", "offset": 0, @@ -806,12 +806,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Validator)18966_storage": { + "t_struct(Validator)19672_storage": { "encoding": "inplace", "label": "struct Validator", "members": [ { - "astId": 18961, + "astId": 19667, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "weight", "offset": 0, @@ -819,7 +819,7 @@ "type": "t_uint256" }, { - "astId": 18963, + "astId": 19669, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "addr", "offset": 0, @@ -827,7 +827,7 @@ "type": "t_address" }, { - "astId": 18965, + "astId": 19671, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "metadata", "offset": 0, @@ -837,12 +837,12 @@ ], "numberOfBytes": "96" }, - "t_struct(ValidatorInfo)18907_storage": { + "t_struct(ValidatorInfo)19613_storage": { "encoding": "inplace", "label": "struct ValidatorInfo", "members": [ { - "astId": 18899, + "astId": 19605, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "federatedPower", "offset": 0, @@ -850,7 +850,7 @@ "type": "t_uint256" }, { - "astId": 18901, + "astId": 19607, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "confirmedCollateral", "offset": 0, @@ -858,7 +858,7 @@ "type": "t_uint256" }, { - "astId": 18903, + "astId": 19609, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "totalCollateral", "offset": 0, @@ -866,7 +866,7 @@ "type": "t_uint256" }, { - "astId": 18906, + "astId": 19612, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "metadata", "offset": 0, @@ -876,20 +876,20 @@ ], "numberOfBytes": "128" }, - "t_struct(ValidatorSet)18942_storage": { + "t_struct(ValidatorSet)19648_storage": { "encoding": "inplace", "label": "struct ValidatorSet", "members": [ { - "astId": 18921, + "astId": 19627, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "permissionMode", "offset": 0, "slot": "0", - "type": "t_enum(PermissionMode)18912" + "type": "t_enum(PermissionMode)19618" }, { - "astId": 18924, + "astId": 19630, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "activeLimit", "offset": 1, @@ -897,7 +897,7 @@ "type": "t_uint16" }, { - "astId": 18927, + "astId": 19633, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "totalConfirmedCollateral", "offset": 0, @@ -905,28 +905,28 @@ "type": "t_uint256" }, { - "astId": 18933, + "astId": 19639, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "validators", "offset": 0, "slot": "2", - "type": "t_mapping(t_address,t_struct(ValidatorInfo)18907_storage)" + "type": "t_mapping(t_address,t_struct(ValidatorInfo)19613_storage)" }, { - "astId": 18937, + "astId": 19643, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "activeValidators", "offset": 0, "slot": "3", - "type": "t_struct(MinPQ)17743_storage" + "type": "t_struct(MinPQ)17670_storage" }, { - "astId": 18941, + "astId": 19647, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "waitingValidators", "offset": 0, "slot": "6", - "type": "t_struct(MaxPQ)17125_storage" + "type": "t_struct(MaxPQ)17052_storage" } ], "numberOfBytes": "288" diff --git a/contracts/binding/src/lib.rs b/contracts/binding/src/lib.rs index dd59524fb0..81be776be5 100644 --- a/contracts/binding/src/lib.rs +++ b/contracts/binding/src/lib.rs @@ -53,6 +53,7 @@ pub mod xnet_messaging_facet; // The list of contracts need to convert FvmAddress to fvm_shared::Address fvm_address_conversion!(gateway_manager_facet); fvm_address_conversion!(gateway_getter_facet); +fvm_address_conversion!(checkpointing_facet); fvm_address_conversion!(xnet_messaging_facet); fvm_address_conversion!(gateway_messenger_facet); fvm_address_conversion!(subnet_actor_checkpointing_facet); diff --git a/contracts/contracts/activities/Activity.sol b/contracts/contracts/activities/Activity.sol new file mode 100644 index 0000000000..a9792598e7 --- /dev/null +++ b/contracts/contracts/activities/Activity.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.23; + +/// The commitments for the child subnet activities that should be submitted to the parent subnet +/// together with a bottom up checkpoint +struct ActivityCommitment { + /// The activity summary for validators + bytes32 summary; + + // TODO: add relayed rewarder commitment +} + +/// The summary for a single validator +struct ValidatorSummary { + /// @dev The validator whose activity we're reporting about. + address validator; + /// @dev The number of blocks committed by each validator in the position they appear in the validators array. + /// If there is a configuration change applied at this checkpoint, this carries information about the _old_ validator set. + uint64 blocksCommitted; + /// @dev Other metadata + bytes metadata; +} + +/// A summary of validator's activity in the child subnet. This is submitted to the parent for reward distribution. +struct ActivitySummary { + /// @dev The block range the activity summary spans; these are the local heights of the start and the end, inclusive. + uint256[2] blockRange; + ValidatorSummary[] activities; +} + +library LibActivitySummary { + function numValidators(ActivitySummary calldata self) internal pure returns(uint64) { + return uint64(self.activities.length); + } + + function commitment(ActivitySummary calldata self) internal pure returns(bytes32) { + return keccak256(abi.encode(self)); + } + + function containsValidator(ActivitySummary calldata self, address validator) internal pure returns(bool) { + uint256 len = self.activities.length; + for (uint256 i = 0; i < len; ) { + if (self.activities[i].validator == validator) { + return true; + } + + unchecked { + i++; + } + } + + return false; + } +} \ No newline at end of file diff --git a/contracts/contracts/interfaces/IValidatorRewarder.sol b/contracts/contracts/activities/IValidatorRewarder.sol similarity index 83% rename from contracts/contracts/interfaces/IValidatorRewarder.sol rename to contracts/contracts/activities/IValidatorRewarder.sol index 6001dfb227..8468ea3040 100644 --- a/contracts/contracts/interfaces/IValidatorRewarder.sol +++ b/contracts/contracts/activities/IValidatorRewarder.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.23; import {SubnetID} from "../structs/Subnet.sol"; +import {ValidatorSummary} from "./Activity.sol"; /// @title ValidatorRewarder interface. /// @@ -12,7 +13,6 @@ import {SubnetID} from "../structs/Subnet.sol"; interface IValidatorRewarder { /// @notice Called by the subnet manager contract to instruct the rewarder to process the subnet summary and /// disburse any relevant rewards. - /// The /// @dev This method should revert if the summary is invalid; this will cause the - function disburseRewards(SubnetID memory id, ActivitySummary memory summary) external; + function disburseRewards(SubnetID calldata id, ValidatorSummary calldata summary) external; } diff --git a/contracts/contracts/activities/LibActivityMerkleVerifier.sol b/contracts/contracts/activities/LibActivityMerkleVerifier.sol new file mode 100644 index 0000000000..4c98c085b6 --- /dev/null +++ b/contracts/contracts/activities/LibActivityMerkleVerifier.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.23; + +import {SubnetID} from "../structs/Subnet.sol"; +import {InvalidProof} from "../errors/IPCErrors.sol"; +import {ValidatorSummary} from "./Activity.sol"; +import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; + +/// Verifies the proof to the commitment in subnet activity summary +library LibActivityMerkleVerifier { + function ensureValidProof(bytes32 commitment, ValidatorSummary calldata summary, bytes32[] calldata proof) internal pure { + // Constructing leaf: https://github.com/OpenZeppelin/merkle-tree#leaf-hash + bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(summary.validator, summary.blocksCommitted, summary.metadata)))); + bool valid = MerkleProof.verify({proof: proof, root: commitment, leaf: leaf}); + if (!valid) { + revert InvalidProof(); + } + } +} diff --git a/contracts/contracts/activities/ValidatorActivityTracker.sol b/contracts/contracts/activities/ValidatorActivityTracker.sol new file mode 100644 index 0000000000..e0bd032288 --- /dev/null +++ b/contracts/contracts/activities/ValidatorActivityTracker.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.23; + +import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; + +import {ValidatorSummary, ActivitySummary} from "./Activity.sol"; +import {SystemContract} from "../lib/LibGatewayActorStorage.sol"; + + +/// The validator reward facet for the child subnet, i.e. for child subnet to track validators's activies +/// and create the commitment. +contract ValidatorActivityTracker is SystemContract { + using EnumerableSet for EnumerableSet.AddressSet; + + /// @dev The starting height of validator's mining activities since the last purged block + uint64 startHeight; + /// @dev The list of validator who have participated in mining since `startHeight` + EnumerableSet.AddressSet validators; + /// Tracks the number of blocks a validator has committed since `startHeight` + mapping(address => uint64) blocksCommitted; + + /// Validators claim their reward for doing work in the child subnet + function recordValidatorActivity(address validator) external systemActorOnly { + blocksCommitted[validator] += 1; + + if (!validators.contains(validator)) { + validators.add(validator); + } + } + + /// Reads the current validator summary + function getSummary() external view returns(ActivitySummary memory summary) { + summary.blockRange = [startHeight, block.number]; + + // prepare the activities + uint256 num_validators = validators.length(); + + summary.activities = new ValidatorSummary[](num_validators); + for (uint256 i = 0; i < num_validators; ) { + address validator = validators.at(i); + bytes memory metadata = new bytes(0); + + summary.activities[i] = ValidatorSummary({ + validator: validator, + blocksCommitted: blocksCommitted[validator], + metadata: metadata + }); + + unchecked { + i++; + } + } + } + + /// Reads the current validator summary and purge the data accordingly + /// @dev Call this method only when bottom up checkpoint needs to be created + function purge_activities() external systemActorOnly { + // prepare the activities + uint256 num_validators = validators.length(); + + for (uint256 i = num_validators - 1; i >= 0; ) { + address validator = validators.at(i); + + delete blocksCommitted[validator]; + validators.remove(validator); + + unchecked { + if (i == 0) { break; } + i--; + } + } + + startHeight = uint64(block.number); + } +} diff --git a/contracts/contracts/activities/ValidatorRewardParentFacet.sol b/contracts/contracts/activities/ValidatorRewardParentFacet.sol new file mode 100644 index 0000000000..e7e7b9ebc4 --- /dev/null +++ b/contracts/contracts/activities/ValidatorRewardParentFacet.sol @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.23; + +import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; + +import {Pausable} from "../lib/LibPausable.sol"; +import {ReentrancyGuard} from "../lib/LibReentrancyGuard.sol"; +import {NotValidator, SubnetNoTargetCommitment, CommitmentAlreadyInitialized, ValidatorAlreadyClaimed} from "../errors/IPCErrors.sol"; +import {ValidatorSummary, ActivitySummary, LibActivitySummary} from "./Activity.sol"; +import {IValidatorRewarder} from "./IValidatorRewarder.sol"; +import {SubnetIDHelper} from "../lib/SubnetIDHelper.sol"; +import {SubnetID} from "../structs/Subnet.sol"; +import {LibActivityMerkleVerifier} from "./LibActivityMerkleVerifier.sol"; + +/// The validator reward facet for the parent subnet, i.e. for validators in the child subnet +/// to claim their reward in the parent subnet, which should be the current subnet this facet +/// is deployed. +contract ValidatorRewardParentFacet is ReentrancyGuard, Pausable { + using LibActivitySummary for ActivitySummary; + + /// Validators claim their reward for doing work in the child subnet + function claim( + SubnetID calldata subnetId, + uint64 checkpointHeight, + ValidatorSummary calldata summary, + bytes32[] calldata proof + ) external nonReentrant whenNotPaused { + // note: No need to check if the subnet is active. If the subnet is not active, the checkpointHeight + // note: will never exist. + + if (msg.sender != summary.validator) { + revert NotValidator(msg.sender); + } + + ValidatorRewardParentStorage storage s = LibValidatorRewardParent.facetStorage(); + + if (s.validatorRewarder == address(0)) { + return handleRelay(); + } + + bytes32 commitment = LibValidatorRewardParent.ensureValidCommitment(s, subnetId, checkpointHeight); + LibActivityMerkleVerifier.ensureValidProof(commitment, summary, proof); + + handleDistribution(s, subnetId, commitment, summary); + + } + + function handleRelay() internal pure { + revert("not implemented yet"); + } + + function handleDistribution( + ValidatorRewardParentStorage storage s, + SubnetID calldata subnetId, + bytes32 commitment, + ValidatorSummary calldata summary + ) internal { + LibValidatorRewardParent.validatorTryClaim(s, commitment, summary.validator); + IValidatorRewarder(s.validatorRewarder).disburseRewards(subnetId, summary); + + // LibValidatorRewardParent.tryPurgeCommitment(s, subnetId, commitment, summary.numValidators()); + } +} + +/// The activity summary commiment that is currently under reward distribution +struct RewardDistribution { + /// The checkpoint height that this distribution + uint64 checkpointHeight; + /// Total number of valdators to claim the distribution + uint64 totalValidators; + /// The list of validators that have claimed the reward + EnumerableSet.AddressSet claimed; +} + +/// Used by the SubnetActor to track the rewards for each validator +struct ValidatorRewardParentStorage { + /// @notice The contract address for validator rewarder + address validatorRewarder; + /// @notice Summaries look up pending to be processed. + /// If the validator rewarder is non-zero, these denote summaries presentable at this level. + /// If the validator rewarder is zero, these summaries must be relayed upwards in the next bottom-up checkpoint. + /// Partitioned by subnet ID (hash) then by checkpoint block height in the child subnet to the commitment + mapping(bytes32 => EnumerableMap.Bytes32ToBytes32Map) commitments; + /// @notice Index over presentable summaries back to the subnet ID, so we can locate them quickly when they're presented. + /// Only used if the validator rewarder is non-zero. + mapping(bytes32 => RewardDistribution) distributions; +} + +/// The payload for list commitments query +struct ListCommimentDetail { + /// The child subnet checkpoint height + uint64 checkpointHeight; + /// The actual commiment of the activities + bytes32 commitment; +} + +library LibValidatorRewardParent { + bytes32 private constant NAMESPACE = keccak256("validator.reward.parent"); + + using SubnetIDHelper for SubnetID; + using EnumerableMap for EnumerableMap.Bytes32ToBytes32Map; + using EnumerableSet for EnumerableSet.AddressSet; + + // =========== External library functions ============= + + function listCommitments(SubnetID calldata subnetId) internal view returns(ListCommimentDetail[] memory listDetails) { + ValidatorRewardParentStorage storage ds = facetStorage(); + + bytes32 subnetKey = subnetId.toHash(); + + uint256 size = ds.commitments[subnetKey].length(); + listDetails = new ListCommimentDetail[](size); + + for (uint256 i = 0; i < size; ) { + (bytes32 heightBytes32, bytes32 commitment) = ds.commitments[subnetKey].at(i); + + listDetails[i] = ListCommimentDetail({ + checkpointHeight: uint64(uint256(heightBytes32)), + commitment: commitment + }); + + unchecked { + i++; + } + } + + return listDetails; + } + + function initNewDistribution(uint64 checkpointHeight, bytes32 commitment, SubnetID calldata subnetId) internal { + ValidatorRewardParentStorage storage ds = facetStorage(); + + bytes32 subnetKey = subnetId.toHash(); + + if (ds.distributions[commitment].checkpointHeight != 0) { + revert CommitmentAlreadyInitialized(); + } + + ds.commitments[subnetKey].set(bytes32(uint256(checkpointHeight)), commitment); + ds.distributions[commitment].checkpointHeight = checkpointHeight; + } + + // ============ Internal library functions ============ + + function facetStorage() internal pure returns (ValidatorRewardParentStorage storage ds) { + bytes32 position = NAMESPACE; + assembly { + ds.slot := position + } + return ds; + } + + function ensureValidCommitment( + ValidatorRewardParentStorage storage ds, + SubnetID calldata subnetId, + uint64 checkpointHeight + ) internal view returns(bytes32) { + bytes32 subnetKey = subnetId.toHash(); + + (bool exists, bytes32 commitment) = ds.commitments[subnetKey].tryGet(bytes32(uint256(checkpointHeight))); + if (!exists) { + revert SubnetNoTargetCommitment(); + } + + // Note: ideally we should check the commitment actually exists, but we dont have to as + // Note: the code will ensure if commitments contains the commitment, + // Note: the commitment will have distribution + // if (ds.distributions[commitment].checkpointHeight == 0) { + // revert CommitmentNotFound(); + // } + + return commitment; + } + + /// Validator tries to claim the reward. The validator can only claim the reward if the validator + /// has not claimed before + function validatorTryClaim(ValidatorRewardParentStorage storage ds, bytes32 commitment, address validator) internal { + if(ds.distributions[commitment].claimed.contains(validator)) { + revert ValidatorAlreadyClaimed(); + } + + ds.distributions[commitment].claimed.add(validator); + } + + /// Try to remove the commiment in the target subnet when ALL VALIDATORS HAVE CLAIMED. + function tryPurgeCommitment( + ValidatorRewardParentStorage storage ds, + SubnetID calldata subnetId, + bytes32 commitment, + uint64 totalValidators + ) internal { + bytes32 subnetKey = subnetId.toHash(); + + if (ds.distributions[commitment].claimed.length() < totalValidators) { + return; + } + + delete ds.commitments[subnetKey]; + delete ds.distributions[commitment]; + } +} \ No newline at end of file diff --git a/contracts/contracts/errors/IPCErrors.sol b/contracts/contracts/errors/IPCErrors.sol index 7f838e1a42..f65028d14c 100644 --- a/contracts/contracts/errors/IPCErrors.sol +++ b/contracts/contracts/errors/IPCErrors.sol @@ -80,6 +80,11 @@ error InvalidFederationPayload(); error DuplicatedGenesisValidator(); error NotEnoughGenesisValidators(); error ValidatorPowerChangeDenied(); +error CommitmentAlreadyInitialized(); +error SubnetNoTargetCommitment(); +error ValidatorAlreadyClaimed(); +error InvalidProof(); + enum InvalidXnetMessageReason { Sender, diff --git a/contracts/contracts/gateway/router/CheckpointingFacet.sol b/contracts/contracts/gateway/router/CheckpointingFacet.sol index 1b55a015a8..b4df277572 100644 --- a/contracts/contracts/gateway/router/CheckpointingFacet.sol +++ b/contracts/contracts/gateway/router/CheckpointingFacet.sol @@ -16,6 +16,7 @@ import {BatchNotCreated, InvalidBatchEpoch, BatchAlreadyExists, NotEnoughSubnetC import {CrossMsgHelper} from "../../lib/CrossMsgHelper.sol"; import {IpcEnvelope, SubnetID} from "../../structs/CrossNet.sol"; import {SubnetIDHelper} from "../../lib/SubnetIDHelper.sol"; +import {LibValidatorRewardParent} from "../../activities/ValidatorRewardParentFacet.sol"; contract CheckpointingFacet is GatewayActorModifiers { using SubnetIDHelper for SubnetID; @@ -41,6 +42,12 @@ contract CheckpointingFacet is GatewayActorModifiers { LibGateway.checkMsgLength(checkpoint.msgs); execBottomUpMsgs(checkpoint.msgs, subnet); + + LibValidatorRewardParent.initNewDistribution( + uint64(checkpoint.blockHeight), + checkpoint.activities.summary, + checkpoint.subnetID + ); } /// @notice creates a new bottom-up checkpoint diff --git a/contracts/contracts/lib/LibGatewayActorStorage.sol b/contracts/contracts/lib/LibGatewayActorStorage.sol index 4cb63536e2..8e98f78f30 100644 --- a/contracts/contracts/lib/LibGatewayActorStorage.sol +++ b/contracts/contracts/lib/LibGatewayActorStorage.sol @@ -102,3 +102,20 @@ contract GatewayActorModifiers { _; } } + +contract SystemContract { + using FilAddress for address; + using FilAddress for address payable; + using AccountHelper for address; + + function _systemActorOnly() private view { + if (!msg.sender.isSystemActor()) { + revert NotSystemActor(); + } + } + + modifier systemActorOnly() { + _systemActorOnly(); + _; + } +} \ No newline at end of file diff --git a/contracts/contracts/lib/LibSubnetActorStorage.sol b/contracts/contracts/lib/LibSubnetActorStorage.sol index 474f84c0f4..eaf800ca5a 100644 --- a/contracts/contracts/lib/LibSubnetActorStorage.sol +++ b/contracts/contracts/lib/LibSubnetActorStorage.sol @@ -65,25 +65,6 @@ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet address[] genesisBalanceKeys; /// @notice The validator gater, if address(0), no validator gating is performed address validatorGater; - - /// BEGIN Validator Rewards. - - /// @notice The validator rewarder. - /// If address(0), this subnet does not process activity summaries, but instead forwards them to the parent - /// network via bottom-up checkpoints. - /// If address(0), and this is the root network, summaries are discarded (> /dev/null). - /// TODO(rewarder): set this address correctly from the constructor. - address validatorRewarder; - /// @notice Summaries pending to be processed. - /// If the validator rewarder is non-zero, these denote summaries presentable at this level. - /// If the validator rewarder is zero, these summaries must be relayed upwards in the next bottom-up checkpoint. - /// Partitioned by subnet ID, in the sequence they must be presented. - /// TODO(rewarder): optimize this pair of data structures. - mapping(SubnetID => bytes32[]) pendingSummaries; - /// @notice Index over presentable summaries back to the subnet ID, so we can locate them quickly when they're presented. - /// Only used if the validator rewarder is non-zero. - /// TODO(rewarder): optimize this pair of data structures. - mapping(bytes32 => SubnetID) presentableSummaries; } library LibSubnetActorStorage { diff --git a/contracts/contracts/structs/CrossNet.sol b/contracts/contracts/structs/CrossNet.sol index 8c96fb1b9a..c11d21236b 100644 --- a/contracts/contracts/structs/CrossNet.sol +++ b/contracts/contracts/structs/CrossNet.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.23; import {SubnetID, IPCAddress} from "./Subnet.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import {ActivityCommitment} from "../activities/Activity.sol"; uint64 constant MAX_MSGS_PER_BATCH = 10; uint256 constant BATCH_PERIOD = 100; @@ -29,11 +30,8 @@ struct BottomUpCheckpoint { uint64 nextConfigurationNumber; /// @dev Batch of messages to execute. IpcEnvelope[] msgs; - /// @dev A commitment to the summary of our chain activity since the previous checkpoint and this one. - bytes32 summary; - /// @dev Summaries relayed upwards from descendants of this subnet. - /// NOTE: Not merkelized to keep it simple, but we will merkelize later to scale better. - RelayedSummary[] relayedSummaries; + /// @dev The activity commitment from child subnet to parent subnet + ActivityCommitment activities; } struct ActivitySummary { diff --git a/contracts/contracts/subnet/SubnetActorRewardFacet.sol b/contracts/contracts/subnet/SubnetActorRewardFacet.sol index 4862e352bb..f34ed6f1ff 100644 --- a/contracts/contracts/subnet/SubnetActorRewardFacet.sol +++ b/contracts/contracts/subnet/SubnetActorRewardFacet.sol @@ -14,17 +14,6 @@ import {Asset} from "../structs/Subnet.sol"; contract SubnetActorRewardFacet is SubnetActorModifiers, ReentrancyGuard, Pausable { using AssetHelper for Asset; - // TODO(rewards): add this function so that relayers can submit summaries to process reward payouts in the root network. - function submitSummary(SubnetID subnetId, ActivitySummary memory summary) external nonReentrant whenNotPaused { - // TODO(rewards): - // 1. Check that the subnet is active. - // 2. Check that the subnet has a non-zero ValidatorRewarder. - // 3. Hash the activity summary to get the commitment. - // 4. Validate that the commitment is pending and presentable, and validate that it matches the expected subnet. - // 5. Send the summary to the ValidatorRewarder#disburseRewards. - // 6. If OK (not reverted), drop the summary from the pending and presentable commitments. - } - /// @notice Validator claims their released collateral. function claim() external nonReentrant whenNotPaused { uint256 amount = LibStaking.claimCollateral(msg.sender); diff --git a/contracts/test/IntegrationTestBase.sol b/contracts/test/IntegrationTestBase.sol index 84eaf54565..967319f1a3 100644 --- a/contracts/test/IntegrationTestBase.sol +++ b/contracts/test/IntegrationTestBase.sol @@ -46,6 +46,9 @@ import {GatewayFacetsHelper} from "./helpers/GatewayFacetsHelper.sol"; import {SubnetActorFacetsHelper} from "./helpers/SubnetActorFacetsHelper.sol"; import {DiamondFacetsHelper} from "./helpers/DiamondFacetsHelper.sol"; +import {ActivityCommitment} from "../../contracts/activities/Activity.sol"; + + struct TestSubnetDefinition { GatewayDiamond gateway; address gatewayAddr; @@ -913,7 +916,8 @@ contract IntegrationTestBase is Test, TestParams, TestRegistry, TestSubnetActor, blockHeight: h, blockHash: keccak256(abi.encode(h)), nextConfigurationNumber: nextConfigNum - 1, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(uint256(nextConfigNum))}) }); vm.deal(address(saDiamond), 100 ether); diff --git a/contracts/test/helpers/SelectorLibrary.sol b/contracts/test/helpers/SelectorLibrary.sol index adcdc5e965..4d3b853a69 100644 --- a/contracts/test/helpers/SelectorLibrary.sol +++ b/contracts/test/helpers/SelectorLibrary.sol @@ -48,7 +48,7 @@ library SelectorLibrary { if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("CheckpointingFacet"))) { return abi.decode( - hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000453b4e7bf00000000000000000000000000000000000000000000000000000000fba0fa4d00000000000000000000000000000000000000000000000000000000dc749b0500000000000000000000000000000000000000000000000000000000ac81837900000000000000000000000000000000000000000000000000000000", + hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000453b4e7bf00000000000000000000000000000000000000000000000000000000024ad232000000000000000000000000000000000000000000000000000000005e6de63200000000000000000000000000000000000000000000000000000000ac81837900000000000000000000000000000000000000000000000000000000", (bytes4[]) ); } @@ -97,7 +97,7 @@ library SelectorLibrary { if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("SubnetActorCheckpointingFacet"))) { return abi.decode( - hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000279979f5700000000000000000000000000000000000000000000000000000000cc2dc2b900000000000000000000000000000000000000000000000000000000", + hex"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002e72f09ca00000000000000000000000000000000000000000000000000000000cc2dc2b900000000000000000000000000000000000000000000000000000000", (bytes4[]) ); } diff --git a/contracts/test/integration/GatewayDiamond.t.sol b/contracts/test/integration/GatewayDiamond.t.sol index 0759b98f08..d9e45d0598 100644 --- a/contracts/test/integration/GatewayDiamond.t.sol +++ b/contracts/test/integration/GatewayDiamond.t.sol @@ -39,6 +39,8 @@ import {GatewayFacetsHelper} from "../helpers/GatewayFacetsHelper.sol"; import {SubnetActorDiamond} from "../../contracts/SubnetActorDiamond.sol"; import {SubnetActorFacetsHelper} from "../helpers/SubnetActorFacetsHelper.sol"; +import {ActivityCommitment} from "../../contracts/activities/Activity.sol"; + contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeTokenMock { using SubnetIDHelper for SubnetID; using CrossMsgHelper for IpcEnvelope; @@ -1067,7 +1069,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHeight: 0, blockHash: keccak256("block1"), nextConfigurationNumber: 1, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(0)}) }); BottomUpCheckpoint memory checkpoint = BottomUpCheckpoint({ @@ -1075,7 +1078,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHeight: gatewayDiamond.getter().bottomUpCheckPeriod(), blockHash: keccak256("block1"), nextConfigurationNumber: 1, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(0)}) }); // failed to create a checkpoint with zero membership weight @@ -1116,7 +1120,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHeight: d, blockHash: keccak256("block"), nextConfigurationNumber: 2, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(0)}) }); vm.startPrank(FilAddress.SYSTEM_ACTOR); @@ -1139,7 +1144,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHeight: gatewayDiamond.getter().bottomUpCheckPeriod(), blockHash: keccak256("block1"), nextConfigurationNumber: 1, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(0)}) }); vm.expectRevert(InvalidCheckpointSource.selector); @@ -1160,7 +1166,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHeight: gatewayDiamond.getter().bottomUpCheckPeriod(), blockHash: keccak256("block1"), nextConfigurationNumber: 1, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(0)}) }); vm.prank(caller); @@ -1206,7 +1213,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHeight: gatewayDiamond.getter().bottomUpCheckPeriod(), blockHash: keccak256("block1"), nextConfigurationNumber: 1, - msgs: msgs + msgs: msgs, + activities: ActivityCommitment({ summary: bytes32(0)}) }); vm.prank(caller); @@ -1226,7 +1234,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHeight: gatewayDiamond.getter().bottomUpCheckPeriod(), blockHash: keccak256("block1"), nextConfigurationNumber: 1, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(0)}) }); BottomUpCheckpoint memory checkpoint2 = BottomUpCheckpoint({ @@ -1234,7 +1243,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHeight: 2 * gatewayDiamond.getter().bottomUpCheckPeriod(), blockHash: keccak256("block2"), nextConfigurationNumber: 1, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(0)}) }); // create a checkpoint @@ -1298,7 +1308,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHeight: gatewayDiamond.getter().bottomUpCheckPeriod(), blockHash: keccak256("block"), nextConfigurationNumber: 1, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(0)}) }); // create a checkpoint @@ -1359,7 +1370,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHeight: gatewayDiamond.getter().bottomUpCheckPeriod(), blockHash: keccak256("block"), nextConfigurationNumber: 1, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(0)}) }); // create a checkpoint @@ -1442,7 +1454,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHeight: gatewayDiamond.getter().bottomUpCheckPeriod(), blockHash: keccak256("block"), nextConfigurationNumber: 1, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(0)}) }); // create a checkpoint @@ -1476,7 +1489,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHeight: gatewayDiamond.getter().bottomUpCheckPeriod(), blockHash: keccak256("block"), nextConfigurationNumber: 1, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(0)}) }); // create a checkpoint @@ -1520,7 +1534,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHeight: gatewayDiamond.getter().bottomUpCheckPeriod(), blockHash: keccak256("block"), nextConfigurationNumber: 1, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(0)}) }); // create a checkpoint @@ -1568,7 +1583,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHeight: i * gatewayDiamond.getter().bottomUpCheckPeriod(), blockHash: keccak256("block"), nextConfigurationNumber: 1, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(0)}) }); gatewayDiamond.checkpointer().createBottomUpCheckpoint(checkpoint, membershipRoot, 10); @@ -1631,7 +1647,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHeight: gatewayDiamond.getter().bottomUpCheckPeriod(), blockHash: keccak256("block1"), nextConfigurationNumber: 1, - msgs: msgs + msgs: msgs, + activities: ActivityCommitment({ summary: bytes32(0)}) }); vm.prank(caller); diff --git a/contracts/test/integration/GatewayDiamondToken.t.sol b/contracts/test/integration/GatewayDiamondToken.t.sol index 74f6223cf3..f191f152b5 100644 --- a/contracts/test/integration/GatewayDiamondToken.t.sol +++ b/contracts/test/integration/GatewayDiamondToken.t.sol @@ -33,6 +33,9 @@ import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.so import {GatewayFacetsHelper} from "../helpers/GatewayFacetsHelper.sol"; +import {ActivityCommitment} from "../../contracts/activities/Activity.sol"; + + contract GatewayDiamondTokenTest is Test, IntegrationTestBase { using SubnetIDHelper for SubnetID; using CrossMsgHelper for IpcEnvelope; @@ -163,7 +166,8 @@ contract GatewayDiamondTokenTest is Test, IntegrationTestBase { blockHash: blockhash(block.number), blockHeight: gatewayDiamond.getter().bottomUpCheckPeriod(), nextConfigurationNumber: 0, - msgs: msgs + msgs: msgs, + activities: ActivityCommitment({ summary: bytes32(0)}) }); vm.prank(address(saDiamond)); @@ -221,7 +225,8 @@ contract GatewayDiamondTokenTest is Test, IntegrationTestBase { blockHash: blockhash(block.number), blockHeight: gatewayDiamond.getter().bottomUpCheckPeriod(), nextConfigurationNumber: 0, - msgs: msgs + msgs: msgs, + activities: ActivityCommitment({ summary: bytes32(0)}) }); // Verify that we received the call and that the recipient has the tokens. diff --git a/contracts/test/integration/MultiSubnet.t.sol b/contracts/test/integration/MultiSubnet.t.sol index 088f828fb0..5fdee611f8 100644 --- a/contracts/test/integration/MultiSubnet.t.sol +++ b/contracts/test/integration/MultiSubnet.t.sol @@ -45,6 +45,8 @@ import {SubnetActorFacetsHelper} from "../helpers/SubnetActorFacetsHelper.sol"; import "forge-std/console.sol"; +import {ActivityCommitment} from "../../contracts/activities/Activity.sol"; + contract MultiSubnetTest is Test, IntegrationTestBase { using SubnetIDHelper for SubnetID; using CrossMsgHelper for IpcEnvelope; @@ -1348,7 +1350,8 @@ contract MultiSubnetTest is Test, IntegrationTestBase { blockHeight: batch.blockHeight, blockHash: keccak256("block1"), nextConfigurationNumber: 0, - msgs: batch.msgs + msgs: batch.msgs, + activities: ActivityCommitment({ summary: bytes32(0)}) }); vm.startPrank(FilAddress.SYSTEM_ACTOR); @@ -1377,7 +1380,8 @@ contract MultiSubnetTest is Test, IntegrationTestBase { blockHeight: e, blockHash: keccak256("block1"), nextConfigurationNumber: 0, - msgs: msgs + msgs: msgs, + activities: ActivityCommitment({ summary: bytes32(0)}) }); vm.startPrank(FilAddress.SYSTEM_ACTOR); diff --git a/contracts/test/integration/SubnetActorDiamond.t.sol b/contracts/test/integration/SubnetActorDiamond.t.sol index 85f57e1356..64ada4509b 100644 --- a/contracts/test/integration/SubnetActorDiamond.t.sol +++ b/contracts/test/integration/SubnetActorDiamond.t.sol @@ -43,6 +43,8 @@ import {GatewayFacetsHelper} from "../helpers/GatewayFacetsHelper.sol"; import {ERC20PresetFixedSupply} from "../helpers/ERC20PresetFixedSupply.sol"; import {SubnetValidatorGater} from "../../contracts/examples/SubnetValidatorGater.sol"; +import {ActivityCommitment} from "../../contracts/activities/Activity.sol"; + contract SubnetActorDiamondTest is Test, IntegrationTestBase { using SubnetIDHelper for SubnetID; using FilAddress for address; @@ -688,7 +690,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHeight: saDiamond.getter().bottomUpCheckPeriod(), blockHash: keccak256("block1"), nextConfigurationNumber: 0, - msgs: msgs + msgs: msgs, + activities: ActivityCommitment({ summary: bytes32(0)}) }); BottomUpCheckpoint memory checkpointWithIncorrectHeight = BottomUpCheckpoint({ @@ -696,7 +699,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHeight: 1, blockHash: keccak256("block1"), nextConfigurationNumber: 0, - msgs: msgs + msgs: msgs, + activities: ActivityCommitment({ summary: bytes32(0)}) }); vm.deal(address(saDiamond), 100 ether); @@ -796,7 +800,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHeight: 1, blockHash: keccak256("block1"), nextConfigurationNumber: 0, - msgs: msgs + msgs: msgs, + activities: ActivityCommitment({ summary: bytes32(0)}) }); BottomUpCheckpoint memory checkpointWithIncorrectHeight = BottomUpCheckpoint({ @@ -804,7 +809,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHeight: 1, blockHash: keccak256("block1"), nextConfigurationNumber: 0, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(uint256(1))}) }); vm.deal(address(saDiamond), 100 ether); @@ -833,6 +839,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { // submit another again checkpoint.blockHeight = 2; + checkpoint.activities = ActivityCommitment({ summary: bytes32(uint256(2))}); hash = keccak256(abi.encode(checkpoint)); for (uint256 i = 0; i < 3; i++) { @@ -888,7 +895,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHeight: 1, blockHash: keccak256("block1"), nextConfigurationNumber: 0, - msgs: msgs + msgs: msgs, + activities: ActivityCommitment({ summary: bytes32(uint256(1) )}) }); submitCheckpointInternal(checkpoint, validators, signatures, keys); require(saDiamond.getter().lastBottomUpCheckpointHeight() == 1, " checkpoint height incorrect"); @@ -900,7 +908,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHeight: 3, blockHash: keccak256("block2"), nextConfigurationNumber: 0, - msgs: msgs + msgs: msgs, + activities: ActivityCommitment({ summary: bytes32(uint256(2))}) }); submitCheckpointInternal(checkpoint, validators, signatures, keys); require(saDiamond.getter().lastBottomUpCheckpointHeight() == 3, " checkpoint height incorrect"); @@ -911,7 +920,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHeight: 2, blockHash: keccak256("block1"), nextConfigurationNumber: 0, - msgs: msgs + msgs: msgs, + activities: ActivityCommitment({ summary: bytes32(uint256(3))}) }); vm.expectRevert(BottomUpCheckpointAlreadySubmitted.selector); submitCheckpointInternal(checkpoint, validators, signatures, keys); @@ -922,7 +932,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHeight: saDiamond.getter().bottomUpCheckPeriod() + 1, blockHash: keccak256("block2"), nextConfigurationNumber: 0, - msgs: msgs + msgs: msgs, + activities: ActivityCommitment({ summary: bytes32(uint256(4))}) }); vm.expectRevert(CannotSubmitFutureCheckpoint.selector); submitCheckpointInternal(checkpoint, validators, signatures, keys); @@ -932,7 +943,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHeight: saDiamond.getter().bottomUpCheckPeriod(), blockHash: keccak256("block2"), nextConfigurationNumber: 0, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(uint256(5))}) }); submitCheckpointInternal(checkpoint, validators, signatures, keys); require( @@ -945,7 +957,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHeight: saDiamond.getter().bottomUpCheckPeriod() + 1, blockHash: keccak256("block2"), nextConfigurationNumber: 0, - msgs: msgs + msgs: msgs, + activities: ActivityCommitment({ summary: bytes32(uint256(6))}) }); submitCheckpointInternal(checkpoint, validators, signatures, keys); require( @@ -958,7 +971,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHeight: saDiamond.getter().bottomUpCheckPeriod() + 2, blockHash: keccak256("block2"), nextConfigurationNumber: 0, - msgs: msgs + msgs: msgs, + activities: ActivityCommitment({ summary: bytes32(uint256(7))}) }); submitCheckpointInternal(checkpoint, validators, signatures, keys); require( @@ -971,7 +985,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHeight: saDiamond.getter().bottomUpCheckPeriod() + 3, blockHash: keccak256("block2"), nextConfigurationNumber: 0, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(uint256(8))}) }); vm.expectRevert(InvalidCheckpointEpoch.selector); submitCheckpointInternal(checkpoint, validators, signatures, keys); @@ -981,7 +996,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHeight: saDiamond.getter().bottomUpCheckPeriod() * 2, blockHash: keccak256("block2"), nextConfigurationNumber: 0, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(uint256(9))}) }); submitCheckpointInternal(checkpoint, validators, signatures, keys); require( @@ -994,7 +1010,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHeight: saDiamond.getter().bottomUpCheckPeriod() * 3, blockHash: keccak256("block2"), nextConfigurationNumber: 0, - msgs: new IpcEnvelope[](0) + msgs: new IpcEnvelope[](0), + activities: ActivityCommitment({ summary: bytes32(uint256(10))}) }); submitCheckpointInternal(checkpoint, validators, signatures, keys); require( @@ -1035,7 +1052,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHeight: saDiamond.getter().bottomUpCheckPeriod(), blockHash: keccak256("block1"), nextConfigurationNumber: 0, - msgs: msgs + msgs: msgs, + activities: ActivityCommitment({ summary: bytes32(0)}) }); vm.deal(address(saDiamond), 100 ether); @@ -1078,7 +1096,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHeight: 2 * saDiamond.getter().bottomUpCheckPeriod(), blockHash: keccak256("block2"), nextConfigurationNumber: 0, - msgs: msgs + msgs: msgs, + activities: ActivityCommitment({ summary: bytes32(uint256(1))}) }); hash = keccak256(abi.encode(checkpoint)); diff --git a/docs/fendermint/observability.md b/docs/fendermint/observability.md index 79ae7a93ac..255c3cf849 100644 --- a/docs/fendermint/observability.md +++ b/docs/fendermint/observability.md @@ -357,9 +357,9 @@ directory = "/path/to/log/directory" max_log_files = 5 # Number of files to keep after rotation rotation = "daily" # Options: minutely, hourly, daily, never ## Optional: filter events by domain -domain_filter = "Bottomup, Consenesus, Mpool, Execution, Topdown, TracingError" +domain_filter = ["Bottomup", "Consensus", "Mpool", "Execution", "Topdown", "System"] ## Optional: filter events by event name -events_filter = "ParentFinalityAcquired, ParentRpcCalled" +events_filter = ["ParentFinalityAcquired", "ParentRpcCalled"] ``` By configuring these options, you can control the behavior of metrics and tracing, enabling fine-grained monitoring and logging for your application. diff --git a/fendermint/actors/activity-tracker/Cargo.toml b/fendermint/actors/activity-tracker/Cargo.toml new file mode 100644 index 0000000000..886262036e --- /dev/null +++ b/fendermint/actors/activity-tracker/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "fendermint_actor_activity_tracker" +description = "Tracks fendermint block mining activities" +license.workspace = true +edition.workspace = true +authors.workspace = true +version = "0.1.0" + +[lib] +## lib is necessary for integration tests +## cdylib is necessary for Wasm build +crate-type = ["cdylib", "lib"] + +[dependencies] +anyhow = { workspace = true } +cid = { workspace = true } +fil_actor_eam = { workspace = true } +fil_actors_runtime = { workspace = true } +fvm_ipld_blockstore = { workspace = true } +fvm_ipld_encoding = { workspace = true } +fvm_shared = { workspace = true } +log = { workspace = true } +multihash = { workspace = true } +num-derive = { workspace = true } +num-traits = { workspace = true } +serde = { workspace = true } +hex-literal = { workspace = true } +frc42_dispatch = { workspace = true } + +[dev-dependencies] +fil_actors_evm_shared = { workspace = true } +fil_actors_runtime = { workspace = true, features = ["test_utils"] } + +[features] +fil-actor = ["fil_actors_runtime/fil-actor"] diff --git a/fendermint/actors/activity-tracker/src/lib.rs b/fendermint/actors/activity-tracker/src/lib.rs new file mode 100644 index 0000000000..4679d15ee3 --- /dev/null +++ b/fendermint/actors/activity-tracker/src/lib.rs @@ -0,0 +1,98 @@ +// Copyright 2021-2023 Protocol Labs +// SPDX-License-Identifier: Apache-2.0, MIT + +use fil_actors_runtime::runtime::{ActorCode, Runtime}; +use fil_actors_runtime::{actor_dispatch, ActorError}; +use fil_actors_runtime::builtin::singletons::SYSTEM_ACTOR_ADDR; +use fvm_ipld_encoding::tuple::*; +use fvm_shared::address::Address; +use fvm_shared::METHOD_CONSTRUCTOR; +use fvm_shared::clock::ChainEpoch; +use num_derive::FromPrimitive; +use fil_actors_runtime::actor_error; + +pub use crate::state::{ValidatorSummary}; +use crate::state::State; + +mod state; + +#[cfg(feature = "fil-actor")] +fil_actors_runtime::wasm_trampoline!(ActivityTrackerActor); + +pub const IPC_ACTIVITY_TRACKER_ACTOR_NAME: &str = "activity"; + +pub struct ActivityTrackerActor; + +#[derive(Deserialize_tuple, Serialize_tuple, Debug, Clone)] +pub struct BlockedMinedParams { + pub validator: Address, +} + +#[derive(Deserialize_tuple, Serialize_tuple, Debug, Clone)] +pub struct GetActivitiesResult { + pub activities: Vec, + pub start_height: ChainEpoch, +} + +#[derive(FromPrimitive)] +#[repr(u64)] +pub enum Method { + Constructor = METHOD_CONSTRUCTOR, + BlockMined = frc42_dispatch::method_hash!("BlockMined"), + GetActivities = frc42_dispatch::method_hash!("GetActivities"), + PurgeActivities = frc42_dispatch::method_hash!("PurgeActivities"), +} + +impl ActivityTrackerActor { + pub fn constructor(rt: &impl Runtime) -> Result<(), ActorError> { + let st = State::new(rt.store())?; + rt.create(&st)?; + + Ok(()) + } + + pub fn block_mined(rt: &impl Runtime, block: BlockedMinedParams) -> Result<(), ActorError> { + rt.validate_immediate_caller_is(std::iter::once(&SYSTEM_ACTOR_ADDR))?; + + rt.transaction(|st: &mut State, rt| { + st.incr_validator_block_committed(rt, &block.validator) + })?; + + Ok(()) + } + + pub fn purge_activities(rt: &impl Runtime) -> Result<(), ActorError> { + rt.validate_immediate_caller_is(std::iter::once(&SYSTEM_ACTOR_ADDR))?; + + rt.transaction(|st: &mut State, rt| { + st.purge_validator_block_committed(rt)?; + st.reset_start_height(rt) + })?; + + Ok(()) + } + + pub fn get_activities(rt: &impl Runtime) -> Result { + let state: State = rt.state()?; + let activities = state.validator_activities(rt)?; + Ok(GetActivitiesResult { + activities, start_height: state.start_height + }) + } + +} + +impl ActorCode for ActivityTrackerActor { + type Methods = Method; + + fn name() -> &'static str { + IPC_ACTIVITY_TRACKER_ACTOR_NAME + } + + actor_dispatch! { + Constructor => constructor, + BlockMined => block_mined, + GetActivities => get_activities, + PurgeActivities => purge_activities, + } +} diff --git a/fendermint/actors/activity-tracker/src/state.rs b/fendermint/actors/activity-tracker/src/state.rs new file mode 100644 index 0000000000..d5ca0d1744 --- /dev/null +++ b/fendermint/actors/activity-tracker/src/state.rs @@ -0,0 +1,80 @@ +// Copyright 2021-2023 Protocol Labs +// SPDX-License-Identifier: Apache-2.0, MIT + +use cid::Cid; +use fil_actors_runtime::runtime::Runtime; +use fil_actors_runtime::{ActorError, Map2, DEFAULT_HAMT_CONFIG}; +use fvm_ipld_blockstore::Blockstore; +use fvm_shared::address::Address; +use fvm_shared::clock::ChainEpoch; +use serde::{Deserialize, Serialize}; + +pub type BlockCommittedMap = Map2; +pub type BlockCommitted = u64; + +#[derive(Deserialize, Serialize, Debug, Clone)] +pub struct ValidatorSummary { + pub validator: Address, + pub block_committed: BlockCommitted, + pub metadata: Vec, +} + +#[derive(Deserialize, Serialize, Debug, Clone)] +pub struct State { + pub start_height: ChainEpoch, + pub blocks_committed: Cid, // BlockCommittedMap +} + +impl State { + pub fn new( + store: &BS, + ) -> Result { + let mut deployers_map = BlockCommittedMap::empty(store, DEFAULT_HAMT_CONFIG, "empty"); + Ok(State { start_height: 0, blocks_committed: deployers_map.flush()? }) + } + + pub fn reset_start_height(&mut self, rt: &impl Runtime) -> Result<(), ActorError> { + self.start_height = rt.curr_epoch(); + Ok(()) + } + + pub fn purge_validator_block_committed(&mut self, rt: &impl Runtime) -> Result<(), ActorError> { + let all_validators = self.validator_activities(rt)?; + let mut validators = BlockCommittedMap::load(rt.store(), &self.blocks_committed, DEFAULT_HAMT_CONFIG, "verifiers")?; + + for v in all_validators { + validators.delete(&v.validator)?; + } + + self.blocks_committed = validators.flush()?; + + Ok(()) + } + + pub fn incr_validator_block_committed(&self, rt: &impl Runtime, validator: &Address) -> Result<(), ActorError> { + let mut validators = BlockCommittedMap::load(rt.store(), &self.blocks_committed, DEFAULT_HAMT_CONFIG, "verifiers")?; + + let v = if let Some(v) = validators.get(validator)? { + *v + 1 + } else { + 1 + }; + + validators.set(validator, v)?; + + Ok(()) + } + + pub fn validator_activities(&self, rt: &impl Runtime) -> Result, ActorError> { + let mut result = vec![]; + + let validators = BlockCommittedMap::load(rt.store(), &self.blocks_committed, DEFAULT_HAMT_CONFIG, "verifiers")?; + validators.for_each(|k, v| { + result.push(ValidatorSummary{ validator: k, block_committed: *v, metadata: vec![]}); + Ok(()) + })?; + + Ok(result) + } +} + diff --git a/fendermint/actors/build.rs b/fendermint/actors/build.rs index 887950ad0a..fc1a180e9a 100644 --- a/fendermint/actors/build.rs +++ b/fendermint/actors/build.rs @@ -8,7 +8,7 @@ use std::path::Path; use std::process::{Command, Stdio}; use std::thread; -const ACTORS: &[&str] = &["chainmetadata", "eam"]; +const ACTORS: &[&str] = &["chainmetadata", "eam", "gas_market"]; const FILES_TO_WATCH: &[&str] = &["Cargo.toml", "src"]; diff --git a/fendermint/actors/gas_market/Cargo.toml b/fendermint/actors/gas_market/Cargo.toml new file mode 100644 index 0000000000..a2ff9f0eb8 --- /dev/null +++ b/fendermint/actors/gas_market/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "fendermint_actor_gas_market" +description = "Builtin transaction gas tracking actor for IPC" +license.workspace = true +edition.workspace = true +authors.workspace = true +version = "0.1.0" + +[lib] +## lib is necessary for integration tests +## cdylib is necessary for Wasm build +crate-type = ["cdylib", "lib"] + +[dependencies] +anyhow = { workspace = true } +cid = { workspace = true } +fil_actors_runtime = { workspace = true } +fvm_ipld_blockstore = { workspace = true } +fvm_ipld_encoding = { workspace = true } +fvm_shared = { workspace = true } +log = { workspace = true } +multihash = { workspace = true } +num-derive = { workspace = true } +num-traits = { workspace = true } +serde = { workspace = true } +hex-literal = { workspace = true } +frc42_dispatch = { workspace = true } + +[dev-dependencies] +fil_actors_evm_shared = { workspace = true } +fil_actors_runtime = { workspace = true, features = ["test_utils"] } + +[features] +fil-actor = ["fil_actors_runtime/fil-actor"] diff --git a/fendermint/actors/gas_market/src/lib.rs b/fendermint/actors/gas_market/src/lib.rs new file mode 100644 index 0000000000..d9b316d584 --- /dev/null +++ b/fendermint/actors/gas_market/src/lib.rs @@ -0,0 +1,371 @@ +// Copyright 2021-2023 Protocol Labs +// SPDX-License-Identifier: Apache-2.0, MIT + +use fil_actors_runtime::actor_error; +use fil_actors_runtime::runtime::{ActorCode, Runtime}; +use fil_actors_runtime::SYSTEM_ACTOR_ADDR; +use fil_actors_runtime::{actor_dispatch, ActorError}; +use fvm_ipld_encoding::tuple::*; +use fvm_shared::econ::TokenAmount; +use fvm_shared::METHOD_CONSTRUCTOR; +use num_derive::FromPrimitive; +use std::cmp::Ordering; + +#[cfg(feature = "fil-actor")] +fil_actors_runtime::wasm_trampoline!(EIP1559GasMarketActor); + +pub const IPC_GAS_MARKET_ACTOR_NAME: &str = "gas_market"; +pub type Gas = u64; +pub type SetConstants = EIP1559Constants; + +/// Constant params used by EIP1559 +#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone)] +pub struct EIP1559Constants { + pub block_gas_limit: Gas, + /// The minimal base fee when gas utilization is low + pub minimal_base_fee: TokenAmount, + /// Elasticity multiplier as defined in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) + pub elasticity_multiplier: u64, + /// Base fee max change denominator as defined in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) + pub base_fee_max_change_denominator: u64, +} + +#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone)] +pub struct EIP1559GasState { + base_fee: TokenAmount, + constants: EIP1559Constants, +} + +#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone)] +pub struct GasActorConstructorParams { + base_fee: TokenAmount, + constants: Option, +} + +#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone)] +pub struct GasMarketReading { + pub block_gas_limit: Gas, + pub base_fee: TokenAmount, +} + +#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone)] +pub struct BlockGasUtilization { + pub block_gas_used: Gas, +} + +#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone)] +pub struct BlockGasUtilizationRet { + pub base_fee: TokenAmount, +} + +pub struct EIP1559GasMarketActor {} + +#[derive(FromPrimitive)] +#[repr(u64)] +pub enum Method { + Constructor = METHOD_CONSTRUCTOR, + CurrentReading = frc42_dispatch::method_hash!("CurrentReading"), + GetConstants = frc42_dispatch::method_hash!("GetConstants"), + SetConstants = frc42_dispatch::method_hash!("SetConstants"), + UpdateUtilization = frc42_dispatch::method_hash!("UpdateUtilization"), +} + +impl EIP1559GasMarketActor { + /// Creates the actor + pub fn constructor( + rt: &impl Runtime, + params: GasActorConstructorParams, + ) -> Result<(), ActorError> { + rt.validate_immediate_caller_is(std::iter::once(&SYSTEM_ACTOR_ADDR))?; + + let st = EIP1559GasState::from(params); + rt.create(&st) + } + + fn set_constants(rt: &impl Runtime, constants: SetConstants) -> Result<(), ActorError> { + rt.validate_immediate_caller_is(std::iter::once(&SYSTEM_ACTOR_ADDR))?; + + rt.transaction(|st: &mut EIP1559GasState, _rt| { + st.constants = constants; + Ok(()) + })?; + + Ok(()) + } + + fn current_reading(rt: &impl Runtime) -> Result { + rt.validate_immediate_caller_accept_any()?; + + let st = rt.state::()?; + Ok(GasMarketReading { + block_gas_limit: st.constants.block_gas_limit, + base_fee: st.base_fee, + }) + } + + fn get_constants(rt: &impl Runtime) -> Result { + rt.validate_immediate_caller_accept_any()?; + + let st = rt.state::()?; + Ok(st.constants) + } + + fn update_utilization( + rt: &impl Runtime, + utilization: BlockGasUtilization, + ) -> Result { + rt.validate_immediate_caller_is(std::iter::once(&SYSTEM_ACTOR_ADDR))?; + + rt.transaction(|st: &mut EIP1559GasState, _rt| { + st.base_fee = st.next_base_fee(utilization.block_gas_used); + Ok(BlockGasUtilizationRet { + base_fee: st.base_fee.clone(), + }) + }) + } +} + +impl Default for EIP1559Constants { + fn default() -> Self { + Self { + // Take from filecoin setting, fvm_shared::BLOCK_GAS_LIMIT + block_gas_limit: 10_000_000_000, + minimal_base_fee: TokenAmount::from_atto(100), + // Elasticity multiplier as defined in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) + elasticity_multiplier: 2, + // Base fee max change denominator as defined in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) + base_fee_max_change_denominator: 8, + } + } +} + +impl From for EIP1559GasState { + fn from(params: GasActorConstructorParams) -> Self { + Self { + base_fee: params.base_fee, + constants: params.constants.unwrap_or_default(), + } + } +} + +impl GasActorConstructorParams { + pub fn new(base_fee: TokenAmount) -> Self { + Self { + base_fee, + constants: None, + } + } + + pub fn with_constants(mut self, constants: EIP1559Constants) -> Self { + self.constants = Some(constants); + self + } +} + +impl EIP1559GasState { + fn next_base_fee(&self, gas_used: Gas) -> TokenAmount { + let base_fee = self.base_fee.clone(); + let gas_target = self.constants.block_gas_limit / self.constants.elasticity_multiplier; + + match gas_used.cmp(&gas_target) { + Ordering::Equal => base_fee, + Ordering::Less => { + let base_fee_delta = base_fee.atto() * (gas_target - gas_used) + / gas_target + / self.constants.base_fee_max_change_denominator; + let base_fee_delta = TokenAmount::from_atto(base_fee_delta); + if base_fee_delta >= base_fee { + self.constants.minimal_base_fee.clone() + } else { + base_fee - base_fee_delta + } + } + Ordering::Greater => { + let gas_used_delta = gas_used - gas_target; + let delta = base_fee.atto() * gas_used_delta + / gas_target + / self.constants.base_fee_max_change_denominator; + base_fee + TokenAmount::from_atto(delta).max(TokenAmount::from_atto(1)) + } + } + } +} + +impl ActorCode for EIP1559GasMarketActor { + type Methods = Method; + + fn name() -> &'static str { + IPC_GAS_MARKET_ACTOR_NAME + } + + actor_dispatch! { + Constructor => constructor, + SetConstants => set_constants, + CurrentReading => current_reading, + GetConstants => get_constants, + UpdateUtilization => update_utilization, + } +} + +#[cfg(test)] +mod tests { + use crate::{ + BlockGasUtilization, EIP1559Constants, EIP1559GasMarketActor, EIP1559GasState, + GasActorConstructorParams, GasMarketReading, Method, + }; + use fil_actors_runtime::test_utils::{expect_empty, MockRuntime, SYSTEM_ACTOR_CODE_ID}; + use fil_actors_runtime::SYSTEM_ACTOR_ADDR; + use fvm_ipld_encoding::ipld_block::IpldBlock; + use fvm_shared::address::Address; + use fvm_shared::econ::TokenAmount; + use fvm_shared::error::ExitCode; + + pub fn construct_and_verify() -> MockRuntime { + let rt = MockRuntime { + receiver: Address::new_id(10), + ..Default::default() + }; + + rt.set_caller(*SYSTEM_ACTOR_CODE_ID, SYSTEM_ACTOR_ADDR); + rt.expect_validate_caller_addr(vec![SYSTEM_ACTOR_ADDR]); + + let result = rt + .call::( + Method::Constructor as u64, + IpldBlock::serialize_cbor(&GasActorConstructorParams { + base_fee: TokenAmount::from_atto(100), + constants: None, + }) + .unwrap(), + ) + .unwrap(); + expect_empty(result); + rt.verify(); + rt.reset(); + + rt + } + + #[test] + fn test_set_ok() { + let rt = construct_and_verify(); + + rt.set_caller(*SYSTEM_ACTOR_CODE_ID, SYSTEM_ACTOR_ADDR); + rt.expect_validate_caller_addr(vec![SYSTEM_ACTOR_ADDR]); + + let r = rt.call::( + Method::SetConstants as u64, + IpldBlock::serialize_cbor(&EIP1559Constants { + minimal_base_fee: Default::default(), + elasticity_multiplier: 0, + base_fee_max_change_denominator: 0, + block_gas_limit: 20, + }) + .unwrap(), + ); + assert!(r.is_ok()); + + let s = rt.get_state::(); + assert_eq!(s.constants.block_gas_limit, 20); + } + + #[test] + fn test_update_utilization_full_usage() { + let rt = construct_and_verify(); + + rt.set_caller(*SYSTEM_ACTOR_CODE_ID, SYSTEM_ACTOR_ADDR); + rt.expect_validate_caller_addr(vec![SYSTEM_ACTOR_ADDR]); + + let r = rt.call::( + Method::UpdateUtilization as u64, + IpldBlock::serialize_cbor(&BlockGasUtilization { + // full block usage + block_gas_used: 10_000_000_000, + }) + .unwrap(), + ); + assert!(r.is_ok()); + + rt.expect_validate_caller_any(); + let r = rt + .call::(Method::CurrentReading as u64, None) + .unwrap() + .unwrap(); + let reading = r.deserialize::().unwrap(); + assert_eq!(reading.base_fee, TokenAmount::from_atto(112)); + } + + #[test] + fn test_update_utilization_equal_usage() { + let rt = construct_and_verify(); + + rt.set_caller(*SYSTEM_ACTOR_CODE_ID, SYSTEM_ACTOR_ADDR); + rt.expect_validate_caller_addr(vec![SYSTEM_ACTOR_ADDR]); + + let r = rt.call::( + Method::UpdateUtilization as u64, + IpldBlock::serialize_cbor(&BlockGasUtilization { + // full block usage + block_gas_used: 5_000_000_000, + }) + .unwrap(), + ); + assert!(r.is_ok()); + + rt.expect_validate_caller_any(); + let r = rt + .call::(Method::CurrentReading as u64, None) + .unwrap() + .unwrap(); + let reading = r.deserialize::().unwrap(); + assert_eq!(reading.base_fee, TokenAmount::from_atto(100)); + } + + #[test] + fn test_update_utilization_under_usage() { + let rt = construct_and_verify(); + + rt.set_caller(*SYSTEM_ACTOR_CODE_ID, SYSTEM_ACTOR_ADDR); + rt.expect_validate_caller_addr(vec![SYSTEM_ACTOR_ADDR]); + + let r = rt.call::( + Method::UpdateUtilization as u64, + IpldBlock::serialize_cbor(&BlockGasUtilization { + // full block usage + block_gas_used: 100_000_000, + }) + .unwrap(), + ); + assert!(r.is_ok()); + + rt.expect_validate_caller_any(); + let r = rt + .call::(Method::CurrentReading as u64, None) + .unwrap() + .unwrap(); + let reading = r.deserialize::().unwrap(); + assert_eq!(reading.base_fee, TokenAmount::from_atto(88)); + } + + #[test] + fn test_not_allowed() { + let rt = construct_and_verify(); + rt.set_caller(*SYSTEM_ACTOR_CODE_ID, Address::new_id(1000)); + rt.expect_validate_caller_addr(vec![SYSTEM_ACTOR_ADDR]); + + let code = rt + .call::( + Method::SetConstants as u64, + IpldBlock::serialize_cbor(&EIP1559Constants { + minimal_base_fee: TokenAmount::from_atto(10000), + elasticity_multiplier: 0, + base_fee_max_change_denominator: 0, + block_gas_limit: 20, + }) + .unwrap(), + ) + .unwrap_err() + .exit_code(); + assert_eq!(code, ExitCode::USR_FORBIDDEN) + } +} diff --git a/fendermint/app/Cargo.toml b/fendermint/app/Cargo.toml index 8e884e69f7..d2b275e1b1 100644 --- a/fendermint/app/Cargo.toml +++ b/fendermint/app/Cargo.toml @@ -51,6 +51,7 @@ fendermint_rocksdb = { path = "../rocksdb" } fendermint_rpc = { path = "../rpc" } fendermint_storage = { path = "../storage" } fendermint_tracing = { path = "../tracing" } +fendermint_actor_gas_market = { path = "../actors/gas_market" } fendermint_vm_actor_interface = { path = "../vm/actor_interface" } fendermint_vm_core = { path = "../vm/core" } fendermint_vm_encoding = { path = "../vm/encoding" } diff --git a/fendermint/app/settings/src/lib.rs b/fendermint/app/settings/src/lib.rs index 1230b3b818..566040dcb2 100644 --- a/fendermint/app/settings/src/lib.rs +++ b/fendermint/app/settings/src/lib.rs @@ -326,12 +326,16 @@ impl Settings { .ignore_empty(true) // otherwise "" will be parsed as a list item .try_parsing(true) // required for list separator .list_separator(",") // need to list keys explicitly below otherwise it can't pase simple `String` type + .with_list_parse_key("tracing.file.domain_filter") + .with_list_parse_key("tracing.file.events_filter") .with_list_parse_key("resolver.connection.external_addresses") .with_list_parse_key("resolver.discovery.static_addresses") .with_list_parse_key("resolver.membership.static_subnets") .with_list_parse_key("eth.cors.allowed_origins") .with_list_parse_key("eth.cors.allowed_methods") - .with_list_parse_key("eth.cors.allowed_headers"), + .with_list_parse_key("eth.cors.allowed_headers") + .with_list_parse_key("eth.tracing.file.domain_filter") + .with_list_parse_key("eth.tracing.file.events_filter"), )) // Set the home directory based on what was passed to the CLI, // so everything in the config can be relative to it. diff --git a/fendermint/app/src/app.rs b/fendermint/app/src/app.rs index c44b9addd6..6d2095267f 100644 --- a/fendermint/app/src/app.rs +++ b/fendermint/app/src/app.rs @@ -41,12 +41,14 @@ use num_traits::Zero; use serde::{Deserialize, Serialize}; use tendermint::abci::request::CheckTxKind; use tendermint::abci::{request, response}; +use tendermint_rpc::Client; use tracing::instrument; use crate::observe::{ BlockCommitted, BlockProposalEvaluated, BlockProposalReceived, BlockProposalSent, Message, MpoolReceived, }; +use crate::validators::ValidatorTracker; use crate::AppExitCode; use crate::BlockHeight; use crate::{tmconv::*, VERSION}; @@ -115,10 +117,11 @@ pub struct AppConfig { /// Handle ABCI requests. #[derive(Clone)] -pub struct App +pub struct App where SS: Blockstore + Clone + 'static, S: KVStore, + C: Client, { /// Database backing all key-value operations. db: Arc, @@ -159,9 +162,13 @@ where /// /// Zero means unlimited. state_hist_size: u64, + /// Tracks the validator + validators: ValidatorTracker, + /// The cometbft client + client: C, } -impl App +impl App where S: KVStore + Codec @@ -170,6 +177,7 @@ where + Codec, DB: KVWritable + KVReadable + Clone + 'static, SS: Blockstore + Clone + 'static, + C: Client + Clone, { pub fn new( config: AppConfig, @@ -178,6 +186,7 @@ where interpreter: I, chain_env: ChainEnv, snapshots: Option, + client: C, ) -> Result { let app = Self { db: Arc::new(db), @@ -192,13 +201,15 @@ where snapshots, exec_state: Arc::new(tokio::sync::Mutex::new(None)), check_state: Arc::new(tokio::sync::Mutex::new(None)), + validators: ValidatorTracker::new(client.clone()), + client, }; app.init_committed_state()?; Ok(app) } } -impl App +impl App where S: KVStore + Codec @@ -207,6 +218,7 @@ where + Codec, DB: KVWritable + KVReadable + 'static + Clone, SS: Blockstore + 'static + Clone, + C: Client, { /// Get an owned clone of the state store. fn state_store_clone(&self) -> SS { @@ -392,7 +404,7 @@ where // the `tower-abci` library would throw an exception when it tried to convert a // `Response::Exception` into a `ConsensusResponse` for example. #[async_trait] -impl Application for App +impl Application for App where S: KVStore + Codec @@ -402,7 +414,10 @@ where S::Namespace: Sync + Send, DB: KVWritable + KVReadable + Clone + Send + Sync + 'static, SS: Blockstore + Clone + Send + Sync + 'static, - I: ProposalInterpreter>, + I: ProposalInterpreter< + State = (ChainEnv, FvmExecState>>), + Message = Vec, + >, I: ExecInterpreter< State = (ChainEnv, FvmExecState), Message = Vec, @@ -420,6 +435,7 @@ where Query = BytesMessageQuery, Output = BytesMessageQueryRes, >, + C: Client + Sync + Clone, { /// Provide information about the ABCI application. async fn info(&self, _request: request::Info) -> AbciResult { @@ -610,13 +626,19 @@ where ); let txs = request.txs.into_iter().map(|tx| tx.to_vec()).collect(); + let state = self + .new_read_only_exec_state()? + .ok_or_else(|| anyhow!("exec state should be present"))?; + let txs = self .interpreter - .prepare(self.chain_env.clone(), txs) + .prepare((self.chain_env.clone(), state), txs) .await .context("failed to prepare proposal")?; let txs = txs.into_iter().map(bytes::Bytes::from).collect(); + // TODO: This seems leaky placed here, should be done in `interpreter`, that's where it's ipc + // TODO: aware, here might have filtered more important messages. let (txs, size) = take_until_max_size(txs, request.max_tx_bytes.try_into().unwrap()); emit(BlockProposalSent { @@ -643,9 +665,13 @@ where let size_txs = txs.iter().map(|tx| tx.len()).sum::(); let num_txs = txs.len(); + let state = self + .new_read_only_exec_state()? + .ok_or_else(|| anyhow!("exec state should be present"))?; + let accept = self .interpreter - .process(self.chain_env.clone(), txs) + .process((self.chain_env.clone(), state), txs) .await .context("failed to process proposal")?; @@ -704,10 +730,14 @@ where state_params.timestamp = to_timestamp(request.header.time); + let validator = self + .validators + .get_validator(&request.header.proposer_address, block_height) + .await?; let state = FvmExecState::new(db, self.multi_engine.as_ref(), block_height, state_params) .context("error creating new state")? .with_block_hash(block_hash) - .with_validator_id(request.header.proposer_address); + .with_validator(validator); tracing::debug!("initialized exec state"); @@ -763,13 +793,20 @@ where // TODO: Return events from epoch transitions. let ret = self - .modify_exec_state(|s| self.interpreter.end(s)) + .modify_exec_state(|s| async { + let ((chain_env, mut state), update) = self.interpreter.end(s).await?; + + let mut end_block = EndBlockUpdate::new(update); + if let Some(gas) = state.gas_market_mut().take_constant_update() { + end_block.update_gas(gas) + } + + Ok(((chain_env, state), end_block)) + }) .await .context("end failed")?; - let r = to_end_block(ret)?; - - Ok(r) + Ok(to_end_block(&self.client, request.height, ret).await?) } /// Commit the current state at the current height. diff --git a/fendermint/app/src/cmd/run.rs b/fendermint/app/src/cmd/run.rs index dca099b1f0..9d8e685169 100644 --- a/fendermint/app/src/cmd/run.rs +++ b/fendermint/app/src/cmd/run.rs @@ -294,7 +294,7 @@ async fn run(settings: Settings) -> anyhow::Result<()> { None }; - let app: App<_, _, AppStore, _> = App::new( + let app: App<_, _, AppStore, _, _> = App::new( AppConfig { app_namespace: ns.app, state_hist_namespace: ns.state_hist, @@ -310,6 +310,7 @@ async fn run(settings: Settings) -> anyhow::Result<()> { parent_finality_votes: parent_finality_votes.clone(), }, snapshots, + tendermint_client.clone(), )?; if let Some((agent_proxy, config)) = ipc_tuple { diff --git a/fendermint/app/src/ipc.rs b/fendermint/app/src/ipc.rs index 6a03bc4b25..5415a0efe7 100644 --- a/fendermint/app/src/ipc.rs +++ b/fendermint/app/src/ipc.rs @@ -15,6 +15,7 @@ use fvm_ipld_blockstore::Blockstore; use std::sync::Arc; use serde::{Deserialize, Serialize}; +use tendermint_rpc::Client; /// All the things that can be voted on in a subnet. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] @@ -24,17 +25,18 @@ pub enum AppVote { } /// Queries the LATEST COMMITTED parent finality from the storage -pub struct AppParentFinalityQuery +pub struct AppParentFinalityQuery where SS: Blockstore + Clone + 'static, S: KVStore, + C: Client, { /// The app to get state - app: App, + app: App, gateway_caller: GatewayCaller>>, } -impl AppParentFinalityQuery +impl AppParentFinalityQuery where S: KVStore + Codec @@ -43,8 +45,9 @@ where + Codec, DB: KVWritable + KVReadable + 'static + Clone, SS: Blockstore + 'static + Clone, + C: Client, { - pub fn new(app: App) -> Self { + pub fn new(app: App) -> Self { Self { app, gateway_caller: GatewayCaller::default(), @@ -62,7 +65,7 @@ where } } -impl ParentFinalityStateQuery for AppParentFinalityQuery +impl ParentFinalityStateQuery for AppParentFinalityQuery where S: KVStore + Codec @@ -71,6 +74,7 @@ where + Codec, DB: KVWritable + KVReadable + 'static + Clone, SS: Blockstore + 'static + Clone, + C: Client, { fn get_latest_committed_finality(&self) -> anyhow::Result> { self.with_exec_state(|mut exec_state| { diff --git a/fendermint/app/src/lib.rs b/fendermint/app/src/lib.rs index f9a45b9a5a..a43f8d93fc 100644 --- a/fendermint/app/src/lib.rs +++ b/fendermint/app/src/lib.rs @@ -8,6 +8,7 @@ pub mod metrics; pub mod observe; mod store; mod tmconv; +mod validators; pub use app::{App, AppConfig}; pub use store::{AppStore, BitswapBlockstore}; diff --git a/fendermint/app/src/tmconv.rs b/fendermint/app/src/tmconv.rs index 984abc4fac..6c031072ec 100644 --- a/fendermint/app/src/tmconv.rs +++ b/fendermint/app/src/tmconv.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0, MIT //! Conversions to Tendermint data types. use anyhow::{anyhow, bail, Context}; +use fendermint_actor_gas_market::SetConstants; use fendermint_vm_core::Timestamp; use fendermint_vm_genesis::{Power, Validator}; use fendermint_vm_interpreter::fvm::{ @@ -10,11 +11,13 @@ use fendermint_vm_interpreter::fvm::{ }; use fendermint_vm_message::signed::DomainHash; use fendermint_vm_snapshot::{SnapshotItem, SnapshotManifest}; +use fvm_shared::clock::ChainEpoch; use fvm_shared::{address::Address, error::ExitCode, event::StampedEvent, ActorID}; use prost::Message; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, num::NonZeroU32}; use tendermint::abci::{response, Code, Event, EventAttribute}; +use tendermint_rpc::Client; use crate::{app::AppError, BlockHeight}; @@ -24,6 +27,25 @@ struct SnapshotMetadata { state_params: FvmStateParams, } +/// The end block update for cometbft +pub struct EndBlockUpdate { + pub max_gas: Option, + pub validators: PowerUpdates, +} + +impl EndBlockUpdate { + pub fn new(power: PowerUpdates) -> Self { + Self { + max_gas: None, + validators: power, + } + } + + pub fn update_gas(&mut self, constants: SetConstants) { + self.max_gas = Some(constants.block_gas_limit); + } +} + /// IPLD encoding of data types we know we must be able to encode. macro_rules! ipld_encode { ($var:ident) => { @@ -32,6 +54,31 @@ macro_rules! ipld_encode { }; } +pub(crate) async fn to_end_block( + client: &C, + height: ChainEpoch, + value: EndBlockUpdate, +) -> anyhow::Result { + let validator_updates = + to_validator_updates(value.validators.0).context("failed to convert validator updates")?; + + let mut consensus_param_updates = None; + if let Some(max_gas) = value.max_gas { + let mut consensus_params = client + .consensus_params(tendermint::block::Height::try_from(height)?) + .await? + .consensus_params; + consensus_params.block.max_gas = max_gas as i64; + consensus_param_updates = Some(consensus_params); + } + + Ok(response::EndBlock { + validator_updates, + consensus_param_updates, + events: Vec::new(), // TODO: Events from epoch transitions? + }) +} + /// Response to delivery where the input was blatantly invalid. /// This indicates that the validator who made the block was Byzantine. pub fn invalid_deliver_tx(err: AppError, description: String) -> response::DeliverTx { @@ -64,6 +111,22 @@ pub fn invalid_query(err: AppError, description: String) -> response::Query { } } +/// Convert validator power to tendermint validator update. +/// TODO: the import is quite strange, `Validator` and `Power` are imported from `genesis` crate, +/// TODO: which should be from a `type` or `validator` crate. +pub fn to_validator_updates( + validators: Vec>, +) -> anyhow::Result> { + let mut updates = vec![]; + for v in validators { + updates.push(tendermint::validator::Update { + pub_key: tendermint::PublicKey::try_from(v.public_key)?, + power: tendermint::vote::Power::try_from(v.power.0)?, + }); + } + Ok(updates) +} + pub fn to_deliver_tx( ret: FvmApplyRet, domain_hash: Option, @@ -148,18 +211,6 @@ pub fn to_check_tx(ret: FvmCheckRet) -> response::CheckTx { } } -/// Map the return values from epoch boundary operations to validator updates. -pub fn to_end_block(power_table: PowerUpdates) -> anyhow::Result { - let validator_updates = - to_validator_updates(power_table.0).context("failed to convert validator updates")?; - - Ok(response::EndBlock { - validator_updates, - consensus_param_updates: None, - events: Vec::new(), // TODO: Events from epoch transitions? - }) -} - /// Map the return values from cron operations. pub fn to_begin_block(ret: FvmApplyRet) -> response::BeginBlock { let events = to_events("event", ret.apply_ret.events, ret.emitters); @@ -319,20 +370,6 @@ pub fn to_query(ret: FvmQueryRet, block_height: BlockHeight) -> anyhow::Result>, -) -> anyhow::Result> { - let mut updates = vec![]; - for v in validators { - updates.push(tendermint::validator::Update { - pub_key: tendermint::PublicKey::try_from(v.public_key)?, - power: tendermint::vote::Power::try_from(v.power.0)?, - }); - } - Ok(updates) -} - pub fn to_timestamp(time: tendermint::time::Time) -> Timestamp { Timestamp( time.unix_timestamp() diff --git a/fendermint/app/src/validators.rs b/fendermint/app/src/validators.rs new file mode 100644 index 0000000000..5870b71606 --- /dev/null +++ b/fendermint/app/src/validators.rs @@ -0,0 +1,69 @@ +// Copyright 2022-2024 Protocol Labs +// SPDX-License-Identifier: Apache-2.0, MIT + +//! Tracks the validator id from tendermint to their corresponding public key. + +use anyhow::anyhow; +use fendermint_crypto::PublicKey; +use fvm_shared::clock::ChainEpoch; +use std::collections::HashMap; +use std::sync::{Arc, RwLock}; +use tendermint::block::Height; +use tendermint_rpc::{Client, Paging}; + +#[derive(Clone)] +pub(crate) struct ValidatorTracker { + client: C, + public_keys: Arc>>, +} + +impl ValidatorTracker { + pub fn new(client: C) -> Self { + Self { + client, + public_keys: Arc::new(RwLock::new(HashMap::new())), + } + } +} + +impl ValidatorTracker { + /// Get the public key of the validator by id. Note that the id is expected to be a validator. + pub async fn get_validator( + &self, + id: &tendermint::account::Id, + height: ChainEpoch, + ) -> anyhow::Result { + if let Some(key) = self.get_from_cache(id) { + return Ok(key); + } + + // this means validators have changed, re-pull all validators + let height = Height::try_from(height)?; + let response = self.client.validators(height, Paging::All).await?; + + let mut new_validators = HashMap::new(); + let mut pubkey = None; + for validator in response.validators { + let p = validator.pub_key.secp256k1().unwrap(); + let compressed = p.to_encoded_point(true); + let b = compressed.as_bytes(); + let key = PublicKey::parse_slice(b, None)?; + + if *id == validator.address { + pubkey = Some(key); + } + + new_validators.insert(validator.address, key); + } + + *self.public_keys.write().unwrap() = new_validators; + + // cannot find the validator, this should not have happened usually + pubkey.ok_or_else(|| anyhow!("{} not validator", id)) + } + + fn get_from_cache(&self, id: &tendermint::account::Id) -> Option { + let keys = self.public_keys.read().unwrap(); + keys.get(id).copied() + } +} diff --git a/fendermint/testing/contract-test/Cargo.toml b/fendermint/testing/contract-test/Cargo.toml index 109e5fae18..643bc26534 100644 --- a/fendermint/testing/contract-test/Cargo.toml +++ b/fendermint/testing/contract-test/Cargo.toml @@ -44,3 +44,5 @@ lazy_static = { workspace = true } bytes = { workspace = true } fvm_ipld_encoding = { workspace = true } multihash = { workspace = true } +fvm = { workspace = true, features = ["testing"] } +fendermint_actor_gas_market = { path = "../../actors/gas_market" } \ No newline at end of file diff --git a/fendermint/testing/contract-test/src/lib.rs b/fendermint/testing/contract-test/src/lib.rs index 65a4ce8ad3..fb9d5236c5 100644 --- a/fendermint/testing/contract-test/src/lib.rs +++ b/fendermint/testing/contract-test/src/lib.rs @@ -4,11 +4,12 @@ use anyhow::{anyhow, Context, Result}; use byteorder::{BigEndian, WriteBytesExt}; use fendermint_vm_core::Timestamp; -use fendermint_vm_interpreter::fvm::PowerUpdates; use fvm_shared::clock::ChainEpoch; use std::{future::Future, sync::Arc}; +use fendermint_crypto::PublicKey; use fendermint_vm_genesis::Genesis; +use fendermint_vm_interpreter::fvm::PowerUpdates; use fendermint_vm_interpreter::genesis::{create_test_genesis_state, GenesisOutput}; use fendermint_vm_interpreter::{ fvm::{ @@ -96,7 +97,7 @@ where } /// Take the execution state, update it, put it back, return the output. - async fn modify_exec_state(&self, f: F) -> anyhow::Result + pub async fn modify_exec_state(&self, f: F) -> anyhow::Result where F: FnOnce(FvmExecState) -> R, R: Future, T)>>, @@ -125,6 +126,14 @@ where } pub async fn begin_block(&self, block_height: ChainEpoch) -> Result<()> { + self.begin_block_with_validator(block_height, None).await + } + + pub async fn begin_block_with_validator( + &self, + block_height: ChainEpoch, + maybe_validator: Option, + ) -> Result<()> { let mut block_hash: [u8; 32] = [0; 32]; let _ = block_hash.as_mut().write_i64::(block_height); @@ -132,9 +141,13 @@ where let mut state_params = self.state_params.clone(); state_params.timestamp = Timestamp(block_height as u64); - let state = FvmExecState::new(db, self.multi_engine.as_ref(), block_height, state_params) - .context("error creating new state")? - .with_block_hash(block_hash); + let mut state = + FvmExecState::new(db, self.multi_engine.as_ref(), block_height, state_params) + .context("error creating new state")? + .with_block_hash(block_hash); + if let Some(validator) = maybe_validator { + state = state.with_validator(validator); + } self.put_exec_state(state).await; @@ -146,6 +159,22 @@ where Ok(()) } + pub async fn execute_msgs(&self, msgs: Vec) -> Result<()> { + self.modify_exec_state(|mut s| async { + for msg in msgs { + let (a, out) = self.interpreter.deliver(s, msg).await?; + if let Some(e) = out.apply_ret.failure_info { + println!("failed: {}", e); + return Err(anyhow!("err in msg deliver")); + } + s = a; + } + Ok((s, ())) + }) + .await + .context("execute msgs failed") + } + pub async fn end_block(&self, _block_height: ChainEpoch) -> Result<()> { let _ret = self .modify_exec_state(|s| self.interpreter.end(s)) diff --git a/fendermint/testing/contract-test/tests/gas_market.rs b/fendermint/testing/contract-test/tests/gas_market.rs new file mode 100644 index 0000000000..5695d08eb8 --- /dev/null +++ b/fendermint/testing/contract-test/tests/gas_market.rs @@ -0,0 +1,333 @@ +// Copyright 2022-2024 Protocol Labs +// SPDX-License-Identifier: Apache-2.0, MIT + +mod staking; + +use anyhow::Context; +use async_trait::async_trait; +use fendermint_actor_gas_market::{GasMarketReading, SetConstants}; +use fendermint_contract_test::Tester; +use fendermint_crypto::{PublicKey, SecretKey}; +use fendermint_vm_actor_interface::eam::EthAddress; +use fendermint_vm_actor_interface::gas::GAS_MARKET_ACTOR_ADDR; +use fendermint_vm_actor_interface::system; +use fendermint_vm_core::Timestamp; +use fendermint_vm_genesis::{Account, Actor, ActorMeta, Genesis, PermissionMode, SignerAddr}; +use fendermint_vm_interpreter::fvm::gas::GasMarket; +use fendermint_vm_interpreter::fvm::state::FvmExecState; +use fendermint_vm_interpreter::fvm::store::memory::MemoryBlockstore; +use fendermint_vm_interpreter::fvm::upgrades::{Upgrade, UpgradeScheduler}; +use fendermint_vm_interpreter::fvm::FvmMessageInterpreter; +use fvm_shared::address::Address; +use fvm_shared::bigint::Zero; +use fvm_shared::clock::ChainEpoch; +use fvm_shared::econ::TokenAmount; +use fvm_shared::message::Message; +use fvm_shared::version::NetworkVersion; +use lazy_static::lazy_static; +use rand::rngs::StdRng; +use rand::SeedableRng; +use tendermint_rpc::Client; + +lazy_static! { + static ref ADDR: Address = + Address::new_secp256k1(&my_secret_key().public_key().serialize()).unwrap(); + static ref ADDR2: Address = + Address::new_secp256k1(&my_secret_key().public_key().serialize()).unwrap(); +} +const CHAIN_NAME: &str = "mychain"; +type I = FvmMessageInterpreter; + +// returns a seeded secret key which is guaranteed to be the same every time +fn my_secret_key() -> SecretKey { + SecretKey::random(&mut StdRng::seed_from_u64(123)) +} + +/// Creates a default tester with validator public key +async fn default_tester() -> (Tester, PublicKey) { + tester_with_upgrader(UpgradeScheduler::new()).await +} + +/// Creates a default tester with validator public key +async fn tester_with_upgrader( + upgrade_scheduler: UpgradeScheduler, +) -> (Tester, PublicKey) { + let validator = my_secret_key().public_key(); + + let interpreter: FvmMessageInterpreter = + FvmMessageInterpreter::new(NeverCallClient, None, 1.05, 1.05, false, upgrade_scheduler); + + let genesis = Genesis { + chain_name: CHAIN_NAME.to_string(), + timestamp: Timestamp(0), + network_version: NetworkVersion::V21, + base_fee: TokenAmount::zero(), + power_scale: 0, + validators: Vec::new(), + accounts: vec![ + Actor { + meta: ActorMeta::Account(Account { + owner: SignerAddr(*ADDR), + }), + balance: TokenAmount::from_whole(100), + }, + Actor { + meta: ActorMeta::Account(Account { + owner: SignerAddr(*ADDR2), + }), + balance: TokenAmount::from_whole(10), + }, + ], + eam_permission_mode: PermissionMode::Unrestricted, + ipc: None, + }; + (Tester::new(interpreter, genesis).await.unwrap(), validator) +} + +#[tokio::test] +async fn test_gas_market_base_fee_oscillation() { + let (mut tester, _) = default_tester().await; + + let num_msgs = 10; + let total_gas_limit = 6178630; + let base_gas_limit = total_gas_limit / num_msgs; + + let mut gas_constants = SetConstants::default(); + gas_constants.block_gas_limit = total_gas_limit; + + let messages = (0..num_msgs) + .map(|i| Message { + version: 0, + from: ADDR.clone(), + to: Address::new_id(10), + sequence: i, + value: TokenAmount::from_atto(1), + method_num: 0, + params: Default::default(), + gas_limit: base_gas_limit, + gas_fee_cap: Default::default(), + gas_premium: TokenAmount::from_atto(1), + }) + .collect::>(); + + // iterate over all the upgrades + let height = 1; + tester.begin_block(height).await.unwrap(); + tester + .modify_exec_state(|mut state| async { + state.gas_market_mut().set_constants(gas_constants); + Ok((state, ())) + }) + .await + .unwrap(); + tester.end_block(height).await.unwrap(); + tester.commit().await.unwrap(); + + let height = 2; + tester.begin_block(height).await.unwrap(); + let before_reading = tester + .modify_exec_state(|mut state| async { + let reading = current_reading(&mut state, height)?; + Ok((state, reading)) + }) + .await + .unwrap(); + tester.execute_msgs(messages).await.unwrap(); + tester.end_block(height).await.unwrap(); + tester.commit().await.unwrap(); + + let height = 3; + tester.begin_block(height).await.unwrap(); + let post_full_block_reading = tester + .modify_exec_state(|mut state| async { + let reading = current_reading(&mut state, height)?; + Ok((state, reading)) + }) + .await + .unwrap(); + tester.end_block(height).await.unwrap(); + tester.commit().await.unwrap(); + assert!( + before_reading.base_fee < post_full_block_reading.base_fee, + "base fee should have increased" + ); + + let height = 4; + tester.begin_block(height).await.unwrap(); + let post_empty_block_reading = tester + .modify_exec_state(|mut state| async { + let reading = current_reading(&mut state, height)?; + Ok((state, reading)) + }) + .await + .unwrap(); + tester.end_block(height).await.unwrap(); + tester.commit().await.unwrap(); + assert!( + post_empty_block_reading.base_fee < post_full_block_reading.base_fee, + "base fee should have decreased" + ); +} + +#[tokio::test] +async fn test_gas_market_premium_distribution() { + let (mut tester, validator) = default_tester().await; + let evm_address = Address::from(EthAddress::new_secp256k1(&validator.serialize()).unwrap()); + + let num_msgs = 10; + let total_gas_limit = 62306300; + let premium = 1; + let base_gas_limit = total_gas_limit / num_msgs; + + let messages = (0..num_msgs) + .map(|i| Message { + version: 0, + from: ADDR.clone(), + to: ADDR2.clone(), + sequence: i, + value: TokenAmount::from_atto(1), + method_num: 0, + params: Default::default(), + gas_limit: base_gas_limit, + gas_fee_cap: TokenAmount::from_atto(base_gas_limit), + gas_premium: TokenAmount::from_atto(premium), + }) + .collect::>(); + + // iterate over all the upgrades + let height = 1; + tester + .begin_block_with_validator(height, Some(validator)) + .await + .unwrap(); + let initial_balance = tester + .modify_exec_state(|state| async { + let tree = state.state_tree(); + let balance = tree + .get_actor_by_address(&evm_address)? + .map(|v| v.balance) + .unwrap_or(TokenAmount::zero()); + Ok((state, balance)) + }) + .await + .unwrap(); + assert_eq!(initial_balance, TokenAmount::zero()); + + tester.execute_msgs(messages).await.unwrap(); + tester.end_block(height).await.unwrap(); + let final_balance = tester + .modify_exec_state(|state| async { + let tree = state.state_tree(); + let balance = tree + .get_actor_by_address(&evm_address)? + .map(|v| v.balance) + .unwrap_or(TokenAmount::zero()); + Ok((state, balance)) + }) + .await + .unwrap(); + tester.commit().await.unwrap(); + + assert!( + final_balance > initial_balance, + "validator balance should have increased" + ) +} + +#[tokio::test] +async fn test_gas_market_upgrade() { + let mut upgrader = UpgradeScheduler::new(); + + let total_gas_limit = 100; + upgrader + .add( + Upgrade::new(CHAIN_NAME, 1, Some(1), |state| { + println!( + "[Upgrade at height {}] Update gas market params", + state.block_height() + ); + + let mut gas_constants = SetConstants::default(); + gas_constants.block_gas_limit = 100; + + state.gas_market_mut().set_constants(gas_constants); + + Ok(()) + }) + .unwrap(), + ) + .unwrap(); + + let (mut tester, _) = tester_with_upgrader(upgrader).await; + + let height = 1; + tester.begin_block(height).await.unwrap(); + let reading = tester + .modify_exec_state(|mut state| async { + let reading = current_reading(&mut state, height)?; + Ok((state, reading)) + }) + .await + .unwrap(); + assert_ne!( + reading.block_gas_limit, total_gas_limit, + "gas limit should not equal at start" + ); + tester.end_block(height).await.unwrap(); + tester.commit().await.unwrap(); + + let height = 2; + tester.begin_block(height).await.unwrap(); + let reading = tester + .modify_exec_state(|mut state| async { + let reading = current_reading(&mut state, height)?; + Ok((state, reading)) + }) + .await + .unwrap(); + assert_eq!( + reading.block_gas_limit, total_gas_limit, + "gas limit should equal after upgrade" + ); +} + +pub fn current_reading( + state: &mut FvmExecState, + block_height: ChainEpoch, +) -> anyhow::Result { + let msg = Message { + from: system::SYSTEM_ACTOR_ADDR, + to: GAS_MARKET_ACTOR_ADDR, + sequence: block_height as u64, + // exclude this from gas restriction + gas_limit: i64::MAX as u64, + method_num: fendermint_actor_gas_market::Method::CurrentReading as u64, + params: fvm_ipld_encoding::RawBytes::default(), + value: Default::default(), + version: Default::default(), + gas_fee_cap: Default::default(), + gas_premium: Default::default(), + }; + let (apply_ret, _) = state.execute_implicit(msg)?; + + if let Some(err) = apply_ret.failure_info { + anyhow::bail!("failed to read gas market state: {}", err); + } + + let r = fvm_ipld_encoding::from_slice::(&apply_ret.msg_receipt.return_data) + .context("failed to parse gas market readying")?; + Ok(r) +} + +#[derive(Clone)] +struct NeverCallClient; + +#[async_trait] +impl Client for NeverCallClient { + async fn perform(&self, _request: R) -> Result + where + R: tendermint_rpc::SimpleRequest, + { + todo!() + } +} diff --git a/fendermint/vm/actor_interface/src/activity.rs b/fendermint/vm/actor_interface/src/activity.rs new file mode 100644 index 0000000000..b0191ee4dc --- /dev/null +++ b/fendermint/vm/actor_interface/src/activity.rs @@ -0,0 +1,4 @@ +// Copyright 2022-2024 Protocol Labs +// SPDX-License-Identifier: Apache-2.0, MIT + +define_id!(ACTIVITY_TRACKER { id: 99 }); \ No newline at end of file diff --git a/fendermint/vm/actor_interface/src/gas.rs b/fendermint/vm/actor_interface/src/gas.rs new file mode 100644 index 0000000000..ccc6c1f18a --- /dev/null +++ b/fendermint/vm/actor_interface/src/gas.rs @@ -0,0 +1,4 @@ +// Copyright 2022-2024 Protocol Labs +// SPDX-License-Identifier: Apache-2.0, MIT + +define_id!(GAS_MARKET { id: 98 }); diff --git a/fendermint/vm/actor_interface/src/lib.rs b/fendermint/vm/actor_interface/src/lib.rs index 2e25c18853..81f0b15e3a 100644 --- a/fendermint/vm/actor_interface/src/lib.rs +++ b/fendermint/vm/actor_interface/src/lib.rs @@ -50,9 +50,11 @@ pub mod diamond; pub mod eam; pub mod ethaccount; pub mod evm; +pub mod gas; pub mod init; pub mod ipc; pub mod multisig; pub mod placeholder; pub mod reward; pub mod system; +pub mod activity; diff --git a/fendermint/vm/interpreter/Cargo.toml b/fendermint/vm/interpreter/Cargo.toml index 8e40ffed5a..c0b7ee33ab 100644 --- a/fendermint/vm/interpreter/Cargo.toml +++ b/fendermint/vm/interpreter/Cargo.toml @@ -23,6 +23,8 @@ fendermint_rpc = { path = "../../rpc" } fendermint_tracing = { path = "../../tracing" } fendermint_actors = { path = "../../actors" } fendermint_actor_chainmetadata = { path = "../../actors/chainmetadata" } +fendermint_actor_gas_market = { path = "../../actors/gas_market" } +fendermint_actor_activity_tracker = { path = "../../actors/activity-tracker" } fendermint_actor_eam = { workspace = true } fendermint_testing = { path = "../../testing", optional = true } ipc_actors_abis = { workspace = true } @@ -67,12 +69,15 @@ arbitrary = { workspace = true, optional = true } quickcheck = { workspace = true, optional = true } rand = { workspace = true, optional = true } +merkle-tree-rs = { path = "../../../ext/merkle-tree-rs" } + [dev-dependencies] quickcheck = { workspace = true } quickcheck_macros = { workspace = true } tempfile = { workspace = true } fendermint_vm_interpreter = { path = ".", features = ["arb"] } +fendermint_vm_message = { path = "../message", features = ["arb"] } fendermint_testing = { path = "../../testing", features = ["golden"] } fvm = { workspace = true, features = ["arb", "testing"] } fendermint_vm_genesis = { path = "../genesis", features = ["arb"] } diff --git a/fendermint/vm/interpreter/src/chain.rs b/fendermint/vm/interpreter/src/chain.rs index 4284c34ecf..2a62dfe373 100644 --- a/fendermint/vm/interpreter/src/chain.rs +++ b/fendermint/vm/interpreter/src/chain.rs @@ -1,14 +1,17 @@ // Copyright 2022-2024 Protocol Labs // SPDX-License-Identifier: Apache-2.0, MIT +use crate::fvm::gas::GasMarket; use crate::fvm::state::ipc::GatewayCaller; +use crate::fvm::store::ReadOnlyBlockstore; use crate::fvm::{topdown, FvmApplyRet, PowerUpdates}; +use crate::selector::{GasLimitSelector, MessageSelector}; use crate::{ fvm::state::FvmExecState, fvm::FvmMessage, signed::{SignedMessageApplyRes, SignedMessageCheckRes, SyntheticMessage, VerifiableMessage}, CheckInterpreter, ExecInterpreter, ProposalInterpreter, QueryInterpreter, }; -use anyhow::{bail, Context}; +use anyhow::{anyhow, bail, Context}; use async_stm::atomically; use async_trait::async_trait; use fendermint_tracing::emit; @@ -102,7 +105,7 @@ where DB: Blockstore + Clone + 'static + Send + Sync, I: Sync + Send, { - type State = ChainEnv; + type State = (ChainEnv, FvmExecState>>); type Message = ChainMessage; /// Check whether there are any "ready" messages in the IPLD resolution mempool which can be appended to the proposal. @@ -111,11 +114,13 @@ where /// account the transactions which are part of top-down or bottom-up checkpoints, to stay within gas limits. async fn prepare( &self, - state: Self::State, + (chain_env, state): Self::State, mut msgs: Vec, ) -> anyhow::Result> { + msgs = messages_selection(msgs, &state)?; + // Collect resolved CIDs ready to be proposed from the pool. - let ckpts = atomically(|| state.checkpoint_pool.collect_resolved()).await; + let ckpts = atomically(|| chain_env.checkpoint_pool.collect_resolved()).await; // Create transactions ready to be included on the chain. let ckpts = ckpts.into_iter().map(|ckpt| match ckpt { @@ -124,14 +129,19 @@ where // Prepare top down proposals. // Before we try to find a quorum, pause incoming votes. This is optional but if there are lots of votes coming in it might hold up proposals. - atomically(|| state.parent_finality_votes.pause_votes_until_find_quorum()).await; + atomically(|| { + chain_env + .parent_finality_votes + .pause_votes_until_find_quorum() + }) + .await; // The pre-requisite for proposal is that there is a quorum of gossiped votes at that height. // The final proposal can be at most as high as the quorum, but can be less if we have already, // hit some limits such as how many blocks we can propose in a single step. let finalities = atomically(|| { - let parent = state.parent_finality_provider.next_proposal()?; - let quorum = state + let parent = chain_env.parent_finality_provider.next_proposal()?; + let quorum = chain_env .parent_finality_votes .find_quorum()? .map(|(height, block_hash)| IPCParentFinality { height, block_hash }); @@ -175,7 +185,13 @@ where } /// Perform finality checks on top-down transactions and availability checks on bottom-up transactions. - async fn process(&self, env: Self::State, msgs: Vec) -> anyhow::Result { + async fn process( + &self, + (chain_env, state): Self::State, + msgs: Vec, + ) -> anyhow::Result { + let mut block_gas_usage = 0; + for msg in msgs { match msg { ChainMessage::Ipc(IpcMessage::BottomUpExec(msg)) => { @@ -187,7 +203,7 @@ where // 1) we validated it when it was relayed, and // 2) if a validator proposes something invalid, we can make them pay during execution. let is_resolved = - atomically(|| match env.checkpoint_pool.get_status(&item)? { + atomically(|| match chain_env.checkpoint_pool.get_status(&item)? { None => Ok(false), Some(status) => status.is_resolved(), }) @@ -206,15 +222,20 @@ where block_hash, }; let is_final = - atomically(|| env.parent_finality_provider.check_proposal(&prop)).await; + atomically(|| chain_env.parent_finality_provider.check_proposal(&prop)) + .await; if !is_final { return Ok(false); } } + ChainMessage::Signed(signed) => { + block_gas_usage += signed.message.gas_limit; + } _ => {} }; } - Ok(true) + + Ok(block_gas_usage <= state.gas_market().available().block_gas) } } @@ -368,7 +389,9 @@ where tracing::debug!("chain interpreter applied topdown msgs"); let local_block_height = state.block_height() as u64; - let proposer = state.validator_id().map(|id| id.to_string()); + let proposer = state + .validator_pubkey() + .map(|id| hex::encode(id.serialize_compressed())); let proposer_ref = proposer.as_deref(); atomically(|| { @@ -531,3 +554,24 @@ fn relayed_bottom_up_ckpt_to_fvm( Ok(msg) } + +fn messages_selection( + msgs: Vec, + state: &FvmExecState, +) -> anyhow::Result> { + let mut signed = msgs + .into_iter() + .map(|msg| match msg { + ChainMessage::Signed(inner) => Ok(inner), + ChainMessage::Ipc(_) => Err(anyhow!("should not have ipc messages in user proposals")), + }) + .collect::>>()?; + + // currently only one selector, we can potentially extend to more selectors + let selectors = vec![GasLimitSelector {}]; + for s in selectors { + signed = s.select_messages(state, signed) + } + + Ok(signed.into_iter().map(ChainMessage::Signed).collect()) +} diff --git a/fendermint/vm/interpreter/src/fvm/activities/actor.rs b/fendermint/vm/interpreter/src/fvm/activities/actor.rs new file mode 100644 index 0000000000..56e6680b41 --- /dev/null +++ b/fendermint/vm/interpreter/src/fvm/activities/actor.rs @@ -0,0 +1,104 @@ +// Copyright 2022-2024 Protocol Labs +// SPDX-License-Identifier: Apache-2.0, MIT + +use fvm::executor::{ApplyKind, ApplyRet, Executor}; +use fvm_shared::clock::ChainEpoch; +use fendermint_actor_activity_tracker::{ValidatorSummary}; +use fendermint_vm_actor_interface::system; +use crate::fvm::activities::{ActivitySummary, BlockMined, ValidatorActivityTracker}; +use crate::fvm::FvmMessage; +use fendermint_vm_actor_interface::activity::ACTIVITY_TRACKER_ACTOR_ADDR; +use fendermint_vm_actor_interface::eam::EthAddress; + +pub struct ActorActivityTracker<'a, E> { + pub(crate) executor: &'a mut E, + pub(crate) epoch: ChainEpoch, +} + +impl <'a, E: Executor> ValidatorActivityTracker for ActorActivityTracker<'a, E> { + type ValidatorSummaryDetail = ValidatorSummary; + + fn track_block_mined(&mut self, block: BlockMined) -> anyhow::Result<()> { + let params = fendermint_actor_activity_tracker::BlockedMinedParams { + validator: fvm_shared::address::Address::from(EthAddress::from(block.validator)), + }; + + let msg = FvmMessage { + from: system::SYSTEM_ACTOR_ADDR, + to: ACTIVITY_TRACKER_ACTOR_ADDR, + sequence: self.epoch as u64, + // exclude this from gas restriction + gas_limit: i64::MAX as u64, + method_num: fendermint_actor_activity_tracker::Method::BlockMined as u64, + params: fvm_ipld_encoding::RawBytes::serialize(params)?, + value: Default::default(), + version: Default::default(), + gas_fee_cap: Default::default(), + gas_premium: Default::default(), + }; + + self.apply_implicit_message(msg)?; + Ok(()) + } + + fn get_activities_summary(&self) -> anyhow::Result> { + // let msg = FvmMessage { + // from: system::SYSTEM_ACTOR_ADDR, + // to: ACTIVITY_TRACKER_ACTOR_ADDR, + // sequence: self.epoch as u64, + // // exclude this from gas restriction + // gas_limit: i64::MAX as u64, + // method_num: fendermint_actor_activity_tracker::Method::GetActivities as u64, + // params: fvm_ipld_encoding::RawBytes::default(), + // value: Default::default(), + // version: Default::default(), + // gas_fee_cap: Default::default(), + // gas_premium: Default::default(), + // }; + // + // let apply_ret = self.apply_implicit_message(msg)?; + // let r = + // fvm_ipld_encoding::from_slice::(&apply_ret.msg_receipt.return_data) + // .context("failed to parse validator activities")?; + // Ok(ActivitySummary { + // block_range: (r.start_height, self.epoch), + // details: r.activities, + // }) + todo!() + } + + fn purge_activities(&mut self) -> anyhow::Result<()> { + let msg = FvmMessage { + from: system::SYSTEM_ACTOR_ADDR, + to: ACTIVITY_TRACKER_ACTOR_ADDR, + sequence: self.epoch as u64, + // exclude this from gas restriction + gas_limit: i64::MAX as u64, + method_num: fendermint_actor_activity_tracker::Method::PurgeActivities as u64, + params: fvm_ipld_encoding::RawBytes::default(), + value: Default::default(), + version: Default::default(), + gas_fee_cap: Default::default(), + gas_premium: Default::default(), + }; + + self.apply_implicit_message(msg)?; + Ok(()) + } +} + +impl <'a, E: Executor> ActorActivityTracker<'a, E> { + fn apply_implicit_message<>( + &mut self, + msg: FvmMessage, + ) -> anyhow::Result { + let raw_length = fvm_ipld_encoding::to_vec(&msg).map(|bz| bz.len())?; + let apply_ret = self.executor.execute_message(msg, ApplyKind::Implicit, raw_length)?; + + if let Some(err) = apply_ret.failure_info { + anyhow::bail!("failed to apply activity tracker messages: {}", err) + } else { + Ok(apply_ret) + } + } +} diff --git a/fendermint/vm/interpreter/src/fvm/activities/merkle.rs b/fendermint/vm/interpreter/src/fvm/activities/merkle.rs new file mode 100644 index 0000000000..db79ff40e6 --- /dev/null +++ b/fendermint/vm/interpreter/src/fvm/activities/merkle.rs @@ -0,0 +1,45 @@ +// Copyright 2022-2024 Protocol Labs +// SPDX-License-Identifier: Apache-2.0, MIT + +use anyhow::Context; +use fendermint_actor_activity_tracker::ValidatorSummary; +use ipc_api::evm::payload_to_evm_address; +use ipc_observability::lazy_static; +use merkle_tree_rs::format::Raw; +use merkle_tree_rs::standard::StandardMerkleTree; + +pub type Hash = ethers::types::H256; + +lazy_static!( + /// ABI types of the Merkle tree which contains validator addresses and their voting power. + pub static ref VALIDATOR_SUMMARY_FIELDS: Vec = vec!["address".to_owned(), "uint64".to_owned(), "bytes".to_owned()]; +); + +/// The merkle tree based proof verification to interact with solidity contracts +pub(crate) struct MerkleProofGen { + tree: StandardMerkleTree, +} + +impl MerkleProofGen { + pub fn root(&self) -> Hash { + self.tree.root() + } +} + +impl TryFrom<&[ValidatorSummary]> for MerkleProofGen { + type Error = anyhow::Error; + + fn try_from(values: &[ValidatorSummary]) -> Result { + let values = values + .iter() + .map(|t| { + payload_to_evm_address(t.validator.payload()) + .map(|addr| vec![format!("{addr:?}"), t.block_committed.to_string(), hex::encode(&t.metadata)]) + }) + .collect::>>()?; + + let tree = StandardMerkleTree::of(&values, &VALIDATOR_SUMMARY_FIELDS) + .context("failed to construct Merkle tree")?; + Ok(MerkleProofGen { tree }) + } +} \ No newline at end of file diff --git a/fendermint/vm/interpreter/src/fvm/activities/mod.rs b/fendermint/vm/interpreter/src/fvm/activities/mod.rs new file mode 100644 index 0000000000..99ab166744 --- /dev/null +++ b/fendermint/vm/interpreter/src/fvm/activities/mod.rs @@ -0,0 +1,46 @@ +// Copyright 2022-2024 Protocol Labs +// SPDX-License-Identifier: Apache-2.0, MIT + +//! Tracks the current blockchain block mining activities and propagates to the parent subnet if +//! needed. + +pub mod actor; +mod merkle; + +use std::fmt::Debug; +use fendermint_actor_activity_tracker::ValidatorSummary; +use fendermint_crypto::PublicKey; +use ipc_api::checkpoint::ActivityCommitment; +use crate::fvm::activities::merkle::MerkleProofGen; + +pub struct BlockMined { + pub(crate) validator: PublicKey, +} + +#[derive(Debug, Clone)] +pub struct ActivitySummary { + pub details: Vec +} + +/// Tracks the validator activities in the current blockchain +pub trait ValidatorActivityTracker { + type ValidatorSummaryDetail: Clone + Debug; + + /// Mark the validator has mined the target block. + fn track_block_mined(&mut self, block: BlockMined) -> anyhow::Result<()>; + + /// Get the validators activities summary since the checkpoint height + fn get_activities_summary(&self) -> anyhow::Result>; + + /// Purge the current validator activities summary + fn purge_activities(&mut self) -> anyhow::Result<()>; +} + +impl ActivitySummary { + pub fn commitment(&self) -> anyhow::Result { + let gen = MerkleProofGen::try_from(self.details.as_slice())?; + Ok(ActivityCommitment{ + summary: gen.root().to_fixed_bytes().to_vec() + }) + } +} \ No newline at end of file diff --git a/fendermint/vm/interpreter/src/fvm/checkpoint.rs b/fendermint/vm/interpreter/src/fvm/checkpoint.rs index 19890678d2..38dea88465 100644 --- a/fendermint/vm/interpreter/src/fvm/checkpoint.rs +++ b/fendermint/vm/interpreter/src/fvm/checkpoint.rs @@ -33,6 +33,7 @@ use super::{ state::{ipc::GatewayCaller, FvmExecState}, ValidatorContext, }; +use crate::fvm::activities::ValidatorActivityTracker; /// Validator voting power snapshot. #[derive(Debug, Clone, PartialEq, Eq)] @@ -96,13 +97,6 @@ where let num_msgs = msgs.len(); - // TODO(rewards): query block producers for the blocks from the last checkpointed epoch to the current one. - // Ideally keep a live cache of block producers, append to it when new blocks are committed, and prune it when generating a checkpoint. - // But for now, we can try to keep it simple and query CometBFT, although that adds latency. - // If we do this, this method seems to be the quickest way: https://docs.cometbft.com/main/rpc/#/Info/block_search - - // TODO(rewards): populate the ActivitySummary struct with the information above, and pass it to the create_bottom_up_checkpoint call. - // Construct checkpoint. let checkpoint = BottomUpCheckpoint { subnet_id, @@ -110,6 +104,7 @@ where block_hash, next_configuration_number, msgs, + activities: state.activities_tracker().get_activities_summary()?.commitment()?.try_into()?, }; // Save the checkpoint in the ledger. @@ -118,6 +113,8 @@ where .create_bottom_up_checkpoint(state, checkpoint.clone(), &curr_power_table.0) .context("failed to store checkpoint")?; + state.activities_tracker().purge_activities()?; + // Figure out the power updates if there was some change in the configuration. let power_updates = if next_configuration_number == 0 { PowerUpdates(Vec::new()) @@ -249,6 +246,9 @@ where block_hash: cp.block_hash, next_configuration_number: cp.next_configuration_number, msgs: convert_tokenizables(cp.msgs)?, + activities: checkpoint::ActivityCommitment { + summary: cp.activities.summary, + } }; // We mustn't do these in parallel because of how nonces are fetched. diff --git a/fendermint/vm/interpreter/src/fvm/exec.rs b/fendermint/vm/interpreter/src/fvm/exec.rs index f53e630a9e..930fda16da 100644 --- a/fendermint/vm/interpreter/src/fvm/exec.rs +++ b/fendermint/vm/interpreter/src/fvm/exec.rs @@ -12,7 +12,11 @@ use fvm_shared::{address::Address, ActorID, MethodNum, BLOCK_GAS_LIMIT}; use ipc_observability::{emit, measure_time, observe::TracingError, Traceable}; use tendermint_rpc::Client; +use crate::fvm::gas::{GasMarket, GasUtilization}; use crate::ExecInterpreter; +use crate::fvm::activities::BlockMined; + +use crate::fvm::activities::ValidatorActivityTracker; use super::{ checkpoint::{self, PowerUpdates}, @@ -157,9 +161,24 @@ where (apply_ret, emitters, latency) } else { + let available_gas = state.gas_market().available().block_gas; + if msg.gas_limit > available_gas { + // This is panic-worthy, but we suppress it to avoid liveness issues. + // Consider maybe record as evidence for the validator slashing? + tracing::warn!( + txn_gas_limit = msg.gas_limit, + block_gas_available = available_gas, + "[ASSERTION FAILED] message gas limit exceed available block gas limit; consensus engine is misbehaving" + ); + } + let (execution_result, latency) = measure_time(|| state.execute_explicit(msg.clone())); let (apply_ret, emitters) = execution_result?; + state + .gas_market_mut() + .record_utilization(GasUtilization::from(&apply_ret)); + (apply_ret, emitters, latency) }; @@ -186,6 +205,12 @@ where } async fn end(&self, mut state: Self::State) -> anyhow::Result<(Self::State, Self::EndOutput)> { + if let Some(pubkey) = state.validator_pubkey() { + state.activities_tracker().track_block_mined(BlockMined { validator: pubkey })?; + } + + state.update_gas_market()?; + // TODO: Consider doing this async, since it's purely informational and not consensus-critical. let _ = checkpoint::emit_trace_if_check_checkpoint_finalized(&self.gateway, &mut state) .inspect_err(|e| { diff --git a/fendermint/vm/interpreter/src/fvm/gas/actor.rs b/fendermint/vm/interpreter/src/fvm/gas/actor.rs new file mode 100644 index 0000000000..6efe355882 --- /dev/null +++ b/fendermint/vm/interpreter/src/fvm/gas/actor.rs @@ -0,0 +1,225 @@ +// Copyright 2022-2024 Protocol Labs +// SPDX-License-Identifier: Apache-2.0, MIT + +use crate::fvm::gas::{Available, CommitRet, Gas, GasMarket, GasUtilization}; +use crate::fvm::FvmMessage; +use anyhow::{anyhow, Context}; + +use fendermint_actor_gas_market::{BlockGasUtilizationRet, GasMarketReading, SetConstants}; +use fendermint_crypto::PublicKey; +use fendermint_vm_actor_interface::eam::EthAddress; +use fendermint_vm_actor_interface::gas::GAS_MARKET_ACTOR_ADDR; +use fendermint_vm_actor_interface::{reward, system}; +use fvm::executor::{ApplyKind, ApplyRet, Executor}; +use fvm_shared::address::Address; +use fvm_shared::clock::ChainEpoch; +use fvm_shared::econ::TokenAmount; +use fvm_shared::METHOD_SEND; + +#[derive(Default)] +pub struct ActorGasMarket { + /// The base fee for fvm + base_fee: TokenAmount, + /// The total gas premium for the miner + gas_premium: TokenAmount, + /// The block gas limit + block_gas_limit: Gas, + /// The accumulated gas usage so far + block_gas_used: Gas, + /// Pending update to the underlying gas actor + constant_update: Option, +} + +impl GasMarket for ActorGasMarket { + type Constant = SetConstants; + + fn set_constants(&mut self, constants: Self::Constant) { + self.constant_update = Some(constants); + } + + fn available(&self) -> Available { + Available { + block_gas: self.block_gas_limit - self.block_gas_used.min(self.block_gas_limit), + } + } + + fn record_utilization(&mut self, utilization: GasUtilization) { + self.gas_premium += utilization.gas_premium; + self.block_gas_used += utilization.gas_used; + + // sanity check + if self.block_gas_used >= self.block_gas_limit { + tracing::warn!("out of block gas, vm execution more than available gas limit"); + } + } +} + +impl ActorGasMarket { + pub fn current_reading( + executor: &mut E, + block_height: ChainEpoch, + ) -> anyhow::Result { + let msg = FvmMessage { + from: system::SYSTEM_ACTOR_ADDR, + to: GAS_MARKET_ACTOR_ADDR, + sequence: block_height as u64, + // exclude this from gas restriction + gas_limit: i64::MAX as u64, + method_num: fendermint_actor_gas_market::Method::CurrentReading as u64, + params: fvm_ipld_encoding::RawBytes::default(), + value: Default::default(), + version: Default::default(), + gas_fee_cap: Default::default(), + gas_premium: Default::default(), + }; + + let raw_length = fvm_ipld_encoding::to_vec(&msg).map(|bz| bz.len())?; + let apply_ret = executor.execute_message(msg, ApplyKind::Implicit, raw_length)?; + + if let Some(err) = apply_ret.failure_info { + anyhow::bail!("failed to read gas market state: {}", err); + } + + let r = + fvm_ipld_encoding::from_slice::(&apply_ret.msg_receipt.return_data) + .context("failed to parse gas market readying")?; + Ok(r) + } + + pub fn create( + executor: &mut E, + block_height: ChainEpoch, + ) -> anyhow::Result { + let reading = Self::current_reading(executor, block_height)?; + Ok(Self { + base_fee: reading.base_fee, + gas_premium: TokenAmount::from_atto(0), + block_gas_limit: reading.block_gas_limit, + block_gas_used: 0, + constant_update: None, + }) + } + + pub fn take_constant_update(&mut self) -> Option { + self.constant_update.take() + } + + pub fn commit( + &self, + executor: &mut E, + block_height: ChainEpoch, + validator: Option, + ) -> anyhow::Result { + self.distribute_reward(executor, block_height, validator)?; + self.commit_constants(executor, block_height)?; + self.commit_utilization(executor, block_height) + } + + fn distribute_reward( + &self, + executor: &mut E, + block_height: ChainEpoch, + validator: Option, + ) -> anyhow::Result<()> { + if validator.is_none() || self.gas_premium.is_zero() { + return Ok(()); + } + + let validator = validator.unwrap(); + let validator = Address::from(EthAddress::new_secp256k1(&validator.serialize())?); + + let msg = FvmMessage { + from: reward::REWARD_ACTOR_ADDR, + to: validator, + sequence: block_height as u64, + // exclude this from gas restriction + gas_limit: i64::MAX as u64, + method_num: METHOD_SEND, + params: fvm_ipld_encoding::RawBytes::default(), + value: self.gas_premium.clone(), + + version: Default::default(), + gas_fee_cap: Default::default(), + gas_premium: Default::default(), + }; + self.apply_implicit_message(msg, executor)?; + + Ok(()) + } + + fn commit_constants( + &self, + executor: &mut E, + block_height: ChainEpoch, + ) -> anyhow::Result<()> { + let Some(ref constants) = self.constant_update else { + return Ok(()); + }; + + let msg = FvmMessage { + from: system::SYSTEM_ACTOR_ADDR, + to: GAS_MARKET_ACTOR_ADDR, + sequence: block_height as u64, + // exclude this from gas restriction + gas_limit: i64::MAX as u64, + method_num: fendermint_actor_gas_market::Method::SetConstants as u64, + params: fvm_ipld_encoding::RawBytes::serialize(constants)?, + value: Default::default(), + version: Default::default(), + gas_fee_cap: Default::default(), + gas_premium: Default::default(), + }; + self.apply_implicit_message(msg, executor)?; + + Ok(()) + } + + fn commit_utilization( + &self, + executor: &mut E, + block_height: ChainEpoch, + ) -> anyhow::Result { + let block_gas_used = self.block_gas_used.min(self.block_gas_limit); + let params = fvm_ipld_encoding::RawBytes::serialize( + fendermint_actor_gas_market::BlockGasUtilization { block_gas_used }, + )?; + + let msg = FvmMessage { + from: system::SYSTEM_ACTOR_ADDR, + to: GAS_MARKET_ACTOR_ADDR, + sequence: block_height as u64, + // exclude this from gas restriction + gas_limit: i64::MAX as u64, + method_num: fendermint_actor_gas_market::Method::UpdateUtilization as u64, + params, + value: Default::default(), + version: Default::default(), + gas_fee_cap: Default::default(), + gas_premium: Default::default(), + }; + + let apply_ret = self.apply_implicit_message(msg, executor)?; + let r = fvm_ipld_encoding::from_slice::( + &apply_ret.msg_receipt.return_data, + ) + .context("failed to parse gas utilization result")?; + Ok(CommitRet { + base_fee: r.base_fee, + }) + } + + fn apply_implicit_message( + &self, + msg: FvmMessage, + executor: &mut E, + ) -> anyhow::Result { + let raw_length = fvm_ipld_encoding::to_vec(&msg).map(|bz| bz.len())?; + let apply_ret = executor.execute_message(msg, ApplyKind::Implicit, raw_length)?; + + if let Some(err) = apply_ret.failure_info { + anyhow::bail!("failed to update EIP1559 gas state: {}", err) + } else { + Ok(apply_ret) + } + } +} diff --git a/fendermint/vm/interpreter/src/fvm/gas/mod.rs b/fendermint/vm/interpreter/src/fvm/gas/mod.rs new file mode 100644 index 0000000000..3d189276f1 --- /dev/null +++ b/fendermint/vm/interpreter/src/fvm/gas/mod.rs @@ -0,0 +1,48 @@ +// Copyright 2022-2024 Protocol Labs +// SPDX-License-Identifier: Apache-2.0, MIT + +use fvm::executor::ApplyRet; +use fvm_shared::econ::TokenAmount; + +pub mod actor; + +pub type Gas = u64; + +pub struct Available { + pub block_gas: Gas, +} + +pub struct CommitRet { + pub base_fee: TokenAmount, +} + +pub struct GasUtilization { + gas_used: Gas, + gas_premium: TokenAmount, +} + +/// The gas market for fendermint. This should be backed by an fvm actor. +pub trait GasMarket { + /// The constant parameters that determines the readings of gas market, such as block gas limit. + type Constant; + + /// Update the constants of the gas market. If the gas market is actor based, then it's recommended + /// to flush at EndBlock. + #[allow(dead_code)] + fn set_constants(&mut self, constants: Self::Constant); + + /// Obtain the current block gas available for execution + fn available(&self) -> Available; + + /// Tracks the amount of gas consumed by a transaction + fn record_utilization(&mut self, gas: GasUtilization); +} + +impl From<&ApplyRet> for GasUtilization { + fn from(ret: &ApplyRet) -> Self { + Self { + gas_used: ret.msg_receipt.gas_used, + gas_premium: ret.miner_tip.clone(), + } + } +} diff --git a/fendermint/vm/interpreter/src/fvm/mod.rs b/fendermint/vm/interpreter/src/fvm/mod.rs index 3e098765b2..0f979036a8 100644 --- a/fendermint/vm/interpreter/src/fvm/mod.rs +++ b/fendermint/vm/interpreter/src/fvm/mod.rs @@ -14,7 +14,9 @@ pub mod upgrades; #[cfg(any(test, feature = "bundle"))] pub mod bundle; +pub mod gas; pub(crate) mod topdown; +pub mod activities; pub use check::FvmCheckRet; pub use checkpoint::PowerUpdates; diff --git a/fendermint/vm/interpreter/src/fvm/state/exec.rs b/fendermint/vm/interpreter/src/fvm/state/exec.rs index 7d5f10dda4..525adffda4 100644 --- a/fendermint/vm/interpreter/src/fvm/state/exec.rs +++ b/fendermint/vm/interpreter/src/fvm/state/exec.rs @@ -5,6 +5,7 @@ use std::collections::{HashMap, HashSet}; use anyhow::Ok; use cid::Cid; +use fendermint_crypto::PublicKey; use fendermint_vm_genesis::PowerScale; use fvm::{ call_manager::DefaultCallManager, @@ -24,19 +25,20 @@ use serde::{Deserialize, Serialize}; use serde_with::serde_as; use crate::fvm::externs::FendermintExterns; +use crate::fvm::gas::actor::ActorGasMarket; use fendermint_vm_core::{chainid::HasChainID, Timestamp}; use fendermint_vm_encoding::IsHumanReadable; +use crate::fvm::activities::actor::ActorActivityTracker; pub type BlockHash = [u8; 32]; -/// First 20 bytes of SHA256(PublicKey) -pub type ValidatorId = tendermint::account::Id; - pub type ActorAddressMap = HashMap; /// The result of the message application bundled with any delegated addresses of event emitters. pub type ExecResult = anyhow::Result<(ApplyRet, ActorAddressMap)>; +pub type StateExecutor = DefaultExecutor>>>>; + /// Parts of the state which evolve during the lifetime of the chain. #[serde_as] #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] @@ -106,13 +108,18 @@ where /// execution interpreter without having to add yet another piece to track at the app level. block_hash: Option, - /// ID of the validator who created this block. For queries and checks this is empty. - validator_id: Option, + /// Public key of the validator who created this block. For queries and checks this is empty. + validator_pubkey: Option, /// State of parameters that are outside the control of the FVM but can change and need to be persisted. params: FvmUpdatableParams, /// Indicate whether the parameters have been updated. params_dirty: bool, + /// Keeps track of block gas usage during execution, and takes care of updating + /// the chosen gas market strategy (by default an on-chain actor delivering EIP-1559 behaviour). + gas_market: ActorGasMarket, + + // chain_info: (NetworkVersion, ChainID, EnginePool), } impl FvmExecState @@ -146,12 +153,13 @@ where let engine = multi_engine.get(&nc)?; let externs = FendermintExterns::new(blockstore.clone(), params.state_root); let machine = DefaultMachine::new(&mc, blockstore, externs)?; - let executor = DefaultExecutor::new(engine, machine)?; + let mut executor = DefaultExecutor::new(engine.clone(), machine)?; + let gas_market = ActorGasMarket::create(&mut executor, block_height)?; Ok(Self { executor, block_hash: None, - validator_id: None, + validator_pubkey: None, params: FvmUpdatableParams { app_version: params.app_version, base_fee: params.base_fee, @@ -159,6 +167,8 @@ where power_scale: params.power_scale, }, params_dirty: false, + gas_market, + // chain_info: (params.network_version, ChainID::from(params.chain_id), engine), }) } @@ -169,11 +179,19 @@ where } /// Set the validator during execution. - pub fn with_validator_id(mut self, validator_id: ValidatorId) -> Self { - self.validator_id = Some(validator_id); + pub fn with_validator(mut self, key: PublicKey) -> Self { + self.validator_pubkey = Some(key); self } + pub fn gas_market_mut(&mut self) -> &mut ActorGasMarket { + &mut self.gas_market + } + + pub fn gas_market(&self) -> &ActorGasMarket { + &self.gas_market + } + /// Execute message implicitly. pub fn execute_implicit(&mut self, msg: Message) -> ExecResult { self.execute_message(msg, ApplyKind::Implicit) @@ -219,8 +237,8 @@ where } /// Identity of the block creator, if we are indeed executing any blocks. - pub fn validator_id(&self) -> Option { - self.validator_id + pub fn validator_pubkey(&self) -> Option { + self.validator_pubkey } /// The timestamp of the currently executing block. @@ -257,6 +275,10 @@ where self.executor.context().network.chain_id } + pub fn activities_tracker(&mut self) -> ActorActivityTracker> { + ActorActivityTracker { epoch: self.block_height(), executor: &mut self.executor } + } + /// Collect all the event emitters' delegated addresses, for those who have any. fn emitter_delegated_addresses(&self, apply_ret: &ApplyRet) -> anyhow::Result { let emitter_ids = apply_ret @@ -286,12 +308,13 @@ where self.update_params(|p| f(&mut p.app_version)) } - /// Update the application version. - pub fn update_base_fee(&mut self, f: F) - where - F: FnOnce(&mut TokenAmount), - { - self.update_params(|p| f(&mut p.base_fee)) + pub fn update_gas_market(&mut self) -> anyhow::Result<()> { + let height = self.block_height(); + let ret = self + .gas_market + .commit(&mut self.executor, height, self.validator_pubkey)?; + self.params.base_fee = ret.base_fee; + Ok(()) } /// Update the circulating supply, effective from the next block. @@ -310,6 +333,19 @@ where f(&mut self.params); self.params_dirty = true; } + + // pub fn call_only(&self) -> FvmCallState { + // let mut nc = NetworkConfig::new(self.chain_info.0); + // nc.chain_id = self.chain_info.1; + // + // let engine = self.chain_info.2.clone(); + // + // self.executor.blockstore().clone() + // let externs = FendermintExterns::new(blockstore.clone(), params.state_root); + // let machine = DefaultMachine::new(&mc, blockstore, externs)?; + // let mut executor = DefaultExecutor::new(engine, machine)?; + // + // } } impl HasChainID for FvmExecState @@ -350,3 +386,20 @@ fn check_error(e: anyhow::Error) -> (ApplyRet, ActorAddressMap) { }; (ret, Default::default()) } + +// /// Compared to FvmExecState, this is used mostly for getters +// pub struct FvmCallState { +// #[allow(clippy::type_complexity)] +// executor: RefCell, FendermintExterns>>>>, +// >>, +// } +// +// impl FvmExecState +// where +// DB: Blockstore + Clone + 'static, +// { +// pub fn call(&self, message: Message) -> anyhow::Result { +// +// } +// } \ No newline at end of file diff --git a/fendermint/vm/interpreter/src/fvm/state/genesis.rs b/fendermint/vm/interpreter/src/fvm/state/genesis.rs index bdbed99473..cbe95c5093 100644 --- a/fendermint/vm/interpreter/src/fvm/state/genesis.rs +++ b/fendermint/vm/interpreter/src/fvm/state/genesis.rs @@ -279,6 +279,23 @@ where self.create_actor_internal(code_cid, id, state, balance, delegated_address) } + pub fn construct_custom_actor( + &mut self, + name: &str, + id: ActorID, + state: &impl Serialize, + balance: TokenAmount, + delegated_address: Option
, + ) -> anyhow::Result<()> { + // Retrieve the CID of the actor code by the numeric ID. + let code_cid = *self + .custom_actor_manifest + .code_by_name(name) + .ok_or_else(|| anyhow!("can't find actor: {name} in the custom actor manifest"))?; + + self.create_actor_internal(code_cid, id, state, balance, delegated_address) + } + /// Creates an actor using code specified in the manifest. fn create_actor_internal( &mut self, diff --git a/fendermint/vm/interpreter/src/genesis.rs b/fendermint/vm/interpreter/src/genesis.rs index 4ccb8fc4bf..8334272363 100644 --- a/fendermint/vm/interpreter/src/genesis.rs +++ b/fendermint/vm/interpreter/src/genesis.rs @@ -19,7 +19,7 @@ use fendermint_vm_actor_interface::diamond::{EthContract, EthContractMap}; use fendermint_vm_actor_interface::eam::EthAddress; use fendermint_vm_actor_interface::ipc::IPC_CONTRACTS; use fendermint_vm_actor_interface::{ - account, burntfunds, chainmetadata, cron, eam, init, ipc, reward, system, EMPTY_ARR, + account, burntfunds, chainmetadata, cron, eam, gas, init, ipc, reward, system, EMPTY_ARR, }; use fendermint_vm_core::{chainid, Timestamp}; use fendermint_vm_genesis::{ActorMeta, Collateral, Genesis, Power, PowerScale, Validator}; @@ -430,6 +430,23 @@ impl GenesisBuilder { ) .context("failed to replace built in eam actor")?; + // currently hard code them for now, once genesis V2 is implemented, should be taken + // from genesis. + // initial base fee as defined in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) + let initial_base_fee = TokenAmount::from_atto(1_000_000_000); + let gas_market_state = fendermint_actor_gas_market::EIP1559GasState::from( + fendermint_actor_gas_market::GasActorConstructorParams::new(initial_base_fee), + ); + state + .create_custom_actor( + fendermint_actor_gas_market::IPC_GAS_MARKET_ACTOR_NAME, + gas::GAS_MARKET_ACTOR_ID, + &gas_market_state, + TokenAmount::zero(), + None, + ) + .context("failed to create gas market actor")?; + // STAGE 2: Create non-builtin accounts which do not have a fixed ID. // The next ID is going to be _after_ the accounts, which have already been assigned an ID by the `Init` actor. diff --git a/fendermint/vm/interpreter/src/lib.rs b/fendermint/vm/interpreter/src/lib.rs index 40868b6cdf..34b3e61b05 100644 --- a/fendermint/vm/interpreter/src/lib.rs +++ b/fendermint/vm/interpreter/src/lib.rs @@ -10,6 +10,7 @@ pub mod signed; #[cfg(feature = "arb")] mod arb; +mod selector; /// Prepare and process transaction proposals. #[async_trait] diff --git a/fendermint/vm/interpreter/src/selector.rs b/fendermint/vm/interpreter/src/selector.rs new file mode 100644 index 0000000000..e3ab7197cb --- /dev/null +++ b/fendermint/vm/interpreter/src/selector.rs @@ -0,0 +1,46 @@ +// Copyright 2022-2024 Protocol Labs +// SPDX-License-Identifier: Apache-2.0, MIT + +//! Gas related message selection + +use crate::fvm::gas::GasMarket; +use crate::fvm::state::FvmExecState; +use fendermint_vm_message::signed::SignedMessage; +use fvm_ipld_blockstore::Blockstore; + +/// Implement this trait to perform message selection +pub trait MessageSelector { + fn select_messages( + &self, + state: &FvmExecState, + msgs: Vec, + ) -> Vec; +} + +pub(crate) struct GasLimitSelector; + +impl MessageSelector for GasLimitSelector { + fn select_messages( + &self, + state: &FvmExecState, + mut msgs: Vec, + ) -> Vec { + let total_gas_limit = state.gas_market().available().block_gas; + + // sort by gas limit descending + msgs.sort_by(|a, b| b.message.gas_limit.cmp(&a.message.gas_limit)); + + let mut total_gas_limit_consumed = 0; + let mut selected = vec![]; + for msg in msgs { + if total_gas_limit_consumed + msg.message.gas_limit <= total_gas_limit { + total_gas_limit_consumed += msg.message.gas_limit; + selected.push(msg); + } else { + break; + } + } + + selected + } +} diff --git a/ipc/api/src/checkpoint.rs b/ipc/api/src/checkpoint.rs index 0d07d701ac..4efc04b7f5 100644 --- a/ipc/api/src/checkpoint.rs +++ b/ipc/api/src/checkpoint.rs @@ -76,6 +76,17 @@ pub struct BottomUpMsgBatch { pub msgs: Vec, } +#[serde_as] +#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] +/// The commitments for the child subnet activities that should be submitted to the parent subnet +/// together with a bottom up checkpoint +pub struct ActivityCommitment { + /// The activity summary for validators + #[serde_as(as = "HumanReadable")] + pub summary: Vec, + // TODO: add relayed activity commitment +} + #[serde_as] #[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] pub struct BottomUpCheckpoint { @@ -94,7 +105,8 @@ pub struct BottomUpCheckpoint { pub next_configuration_number: u64, /// The list of messages for execution pub msgs: Vec, - // TODO(rewards): add new fields and data types for summaries and commitments. + /// The activity commitment from child subnet to parent subnet + pub activities: ActivityCommitment, } pub fn serialize_vec_bytes_to_vec_hex, S>( diff --git a/ipc/api/src/evm.rs b/ipc/api/src/evm.rs index 4c842fea66..72f8fdf137 100644 --- a/ipc/api/src/evm.rs +++ b/ipc/api/src/evm.rs @@ -4,7 +4,7 @@ //! Type conversion for IPC Agent struct with solidity contract struct use crate::address::IPCAddress; -use crate::checkpoint::BottomUpCheckpoint; +use crate::checkpoint::{BottomUpCheckpoint, ActivityCommitment}; use crate::checkpoint::BottomUpMsgBatch; use crate::cross::{IpcEnvelope, IpcMsgKind}; use crate::staking::StakingChange; @@ -21,6 +21,7 @@ use ipc_actors_abis::{ gateway_getter_facet, gateway_manager_facet, gateway_messenger_facet, lib_gateway, register_subnet_facet, subnet_actor_checkpointing_facet, subnet_actor_diamond, subnet_actor_getter_facet, top_down_finality_facet, xnet_messaging_facet, + checkpointing_facet }; /// The type conversion for IPC structs to evm solidity contracts. We need this convenient macro because @@ -121,6 +122,18 @@ macro_rules! cross_msg_types { /// The type conversion between different bottom up checkpoint definition in ethers and sdk macro_rules! bottom_up_checkpoint_conversion { ($module:ident) => { + impl TryFrom for $module::ActivityCommitment { + type Error = anyhow::Error; + + fn try_from(c: ActivityCommitment) -> Result { + Ok( + $module::ActivityCommitment { + summary: c.summary.try_into().map_err(|_| anyhow!("cannot convert bytes32"))?, + } + ) + } + } + impl TryFrom for $module::BottomUpCheckpoint { type Error = anyhow::Error; @@ -135,6 +148,7 @@ macro_rules! bottom_up_checkpoint_conversion { .into_iter() .map($module::IpcEnvelope::try_from) .collect::, _>>()?, + activities: checkpoint.activities.try_into()?, }) } } @@ -153,6 +167,9 @@ macro_rules! bottom_up_checkpoint_conversion { .into_iter() .map(IpcEnvelope::try_from) .collect::, _>>()?, + activities: ActivityCommitment { + summary: value.activities.summary.to_vec(), + }, }) } } @@ -226,13 +243,16 @@ base_type_conversion!(subnet_actor_checkpointing_facet); base_type_conversion!(gateway_getter_facet); base_type_conversion!(gateway_messenger_facet); base_type_conversion!(lib_gateway); +base_type_conversion!(checkpointing_facet); +cross_msg_types!(checkpointing_facet); cross_msg_types!(gateway_getter_facet); cross_msg_types!(xnet_messaging_facet); cross_msg_types!(gateway_messenger_facet); cross_msg_types!(lib_gateway); cross_msg_types!(subnet_actor_checkpointing_facet); +bottom_up_checkpoint_conversion!(checkpointing_facet); bottom_up_checkpoint_conversion!(gateway_getter_facet); bottom_up_checkpoint_conversion!(subnet_actor_checkpointing_facet); bottom_up_msg_batch_conversion!(gateway_getter_facet); diff --git a/ipc/cli/src/commands/subnet/validator.rs b/ipc/cli/src/commands/subnet/validator.rs index f73f5669f6..ad5b79b8d8 100644 --- a/ipc/cli/src/commands/subnet/validator.rs +++ b/ipc/cli/src/commands/subnet/validator.rs @@ -2,15 +2,15 @@ // SPDX-License-Identifier: MIT //! Get the validator information +use crate::{get_ipc_provider, CommandLineHandler, GlobalArguments}; use async_trait::async_trait; use clap::Args; use fvm_shared::address::Address; use ipc_api::subnet_id::SubnetID; +use ipc_types::EthAddress; use std::fmt::Debug; use std::str::FromStr; -use crate::{get_ipc_provider, CommandLineHandler, GlobalArguments}; - /// The command to get the validator information pub(crate) struct ValidatorInfo; @@ -23,7 +23,11 @@ impl CommandLineHandler for ValidatorInfo { let provider = get_ipc_provider(global)?; let subnet = SubnetID::from_str(&arguments.subnet)?; - let validator = Address::from_str(&arguments.validator)?; + // Attempt to parse the validator address as an EthAddress first; if not, parse as a + // Filecoin address. + let validator: Address = EthAddress::from_str(&arguments.validator) + .map(EthAddress::into) + .or_else(|_| Address::from_str(&arguments.validator))?; let validator_info = provider.get_validator_info(&subnet, &validator).await?; println!("{}", validator_info); @@ -37,6 +41,9 @@ impl CommandLineHandler for ValidatorInfo { pub(crate) struct ValidatorInfoArgs { #[arg(long, help = "The subnet id to query validator info")] pub subnet: String, - #[arg(long, help = "The validator address")] + #[arg( + long, + help = "The validator address, in 0x Eth format or Filecoin address format" + )] pub validator: String, } diff --git a/ipc/observability/src/config.rs b/ipc/observability/src/config.rs index 50973f767a..1a73fa905a 100644 --- a/ipc/observability/src/config.rs +++ b/ipc/observability/src/config.rs @@ -12,6 +12,7 @@ use tracing_subscriber::filter::EnvFilter; #[serde_as] #[derive(Debug, Deserialize, Clone, Default, strum::EnumString, strum::Display)] #[strum(serialize_all = "snake_case")] +#[serde(rename_all = "lowercase")] pub enum LogLevel { Off, Error, @@ -32,6 +33,7 @@ impl From for EnvFilter { #[serde_as] #[derive(Debug, Deserialize, Clone, strum::EnumString, strum::Display)] #[strum(serialize_all = "snake_case")] +#[serde(rename_all = "lowercase")] pub enum RotationKind { Minutely, Hourly,