diff --git a/src/bindings/specs/v1 forest-1dcbf7afd00-path-v1.json b/src/bindings/specs/v1 forest_9d76a71562f_path_v1.json similarity index 96% rename from src/bindings/specs/v1 forest-1dcbf7afd00-path-v1.json rename to src/bindings/specs/v1 forest_9d76a71562f_path_v1.json index 1c19617..84d251c 100644 --- a/src/bindings/specs/v1 forest-1dcbf7afd00-path-v1.json +++ b/src/bindings/specs/v1 forest_9d76a71562f_path_v1.json @@ -2,7 +2,7 @@ "openrpc": "1.3.2", "info": { "title": "forest", - "version": "0.20.0" + "version": "0.21.1" }, "methods": [ { @@ -935,6 +935,26 @@ }, "paramStructure": "by-position" }, + { + "name": "Filecoin.EthGetLogs", + "params": [ + { + "name": "eth_filter", + "required": true, + "schema": { + "$ref": "#/components/schemas/EthFilterSpec" + } + } + ], + "result": { + "name": "Filecoin.EthGetLogs.Result", + "required": true, + "schema": { + "$ref": "#/components/schemas/EthFilterResult" + } + }, + "paramStructure": "by-position" + }, { "name": "Filecoin.EthGetMessageCidByTransactionHash", "params": [ @@ -4733,7 +4753,13 @@ "name": "tipset_key", "required": true, "schema": { - "$ref": "#/components/schemas/F3TipSetKey" + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/components/schemas/Cid" + } } } ], @@ -4759,7 +4785,13 @@ "name": "tipset_key", "required": true, "schema": { - "$ref": "#/components/schemas/F3TipSetKey" + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/components/schemas/Cid" + } } } ], @@ -4786,10 +4818,40 @@ "result": { "name": "Filecoin.F3GetProgress.Result", "required": true, + "schema": { + "$ref": "#/components/schemas/F3Instant" + } + }, + "paramStructure": "by-position" + }, + { + "name": "Filecoin.F3GetManifest", + "params": [], + "result": { + "name": "Filecoin.F3GetManifest.Result", + "required": true, "schema": true }, "paramStructure": "by-position" }, + { + "name": "Filecoin.F3ListParticipants", + "params": [], + "result": { + "name": "Filecoin.F3ListParticipants.Result", + "required": false, + "schema": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/components/schemas/F3Participant" + } + } + }, + "paramStructure": "by-position" + }, { "name": "Filecoin.F3GetLatestCertificate", "params": [], @@ -4801,7 +4863,7 @@ "paramStructure": "by-position" }, { - "name": "Filecoin.F3Participate", + "name": "Filecoin.F3GetOrRenewParticipationTicket", "params": [ { "name": "miner_address", @@ -4811,19 +4873,39 @@ } }, { - "name": "new_lease_expiration", + "name": "previous_lease_ticket", "required": true, "schema": { - "type": "string", - "format": "date-time" + "$ref": "#/components/schemas/Base64String" } }, { - "name": "old_lease_expiration", + "name": "instances", + "required": true, + "schema": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } + ], + "result": { + "name": "Filecoin.F3GetOrRenewParticipationTicket.Result", + "required": true, + "schema": { + "$ref": "#/components/schemas/Base64String" + } + }, + "paramStructure": "by-position" + }, + { + "name": "Filecoin.F3Participate", + "params": [ + { + "name": "lease_ticket", "required": true, "schema": { - "type": "string", - "format": "date-time" + "$ref": "#/components/schemas/Base64String" } } ], @@ -4831,7 +4913,7 @@ "name": "Filecoin.F3Participate.Result", "required": true, "schema": { - "type": "boolean" + "$ref": "#/components/schemas/ApiF3ParticipationLease" } }, "paramStructure": "by-position" @@ -5493,6 +5575,45 @@ } } }, + "ApiF3ParticipationLease": { + "description": "defines the lease granted to a storage provider for participating in F3 consensus, detailing the session identifier, issuer, subject, and the expiration instance.", + "type": "object", + "required": [ + "FromInstance", + "Issuer", + "MinerID", + "Network", + "ValidityTerm" + ], + "properties": { + "FromInstance": { + "description": "specifies the instance ID from which this lease is valid.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "Issuer": { + "description": "the identity of the node that issued the lease.", + "type": "string" + }, + "MinerID": { + "description": "the actor ID of the miner that holds the lease.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "Network": { + "description": "the name of the network this lease belongs to.", + "type": "string" + }, + "ValidityTerm": { + "description": "specifies the number of instances for which the lease remains valid from the FromInstance.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } + }, "ApiInvocResult": { "type": "object", "required": [ @@ -6230,12 +6351,34 @@ } } }, + "EthFilterResult": { + "description": "`EthFilterResult` represents the response from executing a filter: - A list of block hashes - A list of transaction hashes - Or a list of logs", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/components/schemas/EthHash" + } + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/EthHash" + } + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/EthLog" + } + } + ] + }, "EthFilterSpec": { "description": "Represents a filter specification for querying Ethereum event logs. This struct can be used to specify criteria for filtering Ethereum event logs based on block range, address, topics, and block hash. It is useful for making requests to Ethereum nodes to fetch logs that match certain conditions.\n\n# Fields\n\n* `from_block` - Optional field interpreted as an epoch (in hex): - `\"latest\"`: latest mined block. - `\"earliest\"`: first block. - `\"pending\"`: blocks that have not yet been mined. If omitted, the default value is `\"latest\"`. This field is skipped during serialization if `None`.\n\n* `to_block` - Optional field interpreted as an epoch (in hex): - `\"latest\"`: latest mined block. - `\"earliest\"`: first block. - `\"pending\"`: blocks that have not yet been mined. If omitted, the default value is `\"latest\"`. This field is skipped during serialization if `None`.\n\n* `address` - Actor address or a list of addresses (`Vec`) from which event logs should originate. If the filter needs to match a single address, it can be specified as single element vector. This field is required and cannot be omitted.\n\n* `topics` - List of topics (`EthTopicSpec`) to be matched in the event logs.\n\n* `block_hash` - Optional field specifying a block hash (`Hash`) Restricts event logs returned to those emitted from messages contained in this tipset. When `block_hash` is provided, neither `from_block` nor `to_block` can be specified. This field is skipped during serialization if `None`. [the spec](https://github.com/filecoin-project/lotus/blob/475139ff95407ed9d55d3a2ef87e28da66512937/chain/types/ethtypes/eth_types.go#L602-L627).", "type": "object", "required": [ - "address", - "topics" + "address" ], "properties": { "address": { @@ -6267,7 +6410,14 @@ ] }, "topics": { - "$ref": "#/components/schemas/EthTopicSpec" + "anyOf": [ + { + "$ref": "#/components/schemas/EthTopicSpec" + }, + { + "type": "null" + } + ] } } }, @@ -6275,10 +6425,25 @@ "type": "string" }, "EthHashList": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EthHash" - } + "description": "`EthHashList` represents a topic filter that can take one of two forms: - `List`: Matches if the hash is present in the vector. - `Single`: An optional hash, where: - `Some(hash)`: Matches exactly this hash. - `None`: Acts as a wildcard.", + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/components/schemas/EthHash" + } + }, + { + "anyOf": [ + { + "$ref": "#/components/schemas/EthHash" + }, + { + "type": "null" + } + ] + } + ] }, "EthInt64": { "type": "string" @@ -6299,33 +6464,42 @@ ], "properties": { "address": { + "description": "The address of the actor that produced the event log.", "$ref": "#/components/schemas/EthAddress" }, "blockHash": { + "description": "The hash of the tipset containing the message that produced the log.", "$ref": "#/components/schemas/EthHash" }, "blockNumber": { + "description": "The epoch of the tipset containing the message.", "$ref": "#/components/schemas/EthUint64" }, "data": { + "description": "The value of the event log, excluding topics.", "$ref": "#/components/schemas/EthBytes" }, "logIndex": { + "description": "The index of the event log in the sequence of events produced by the message execution. (this is the index in the events AMT on the message receipt)", "$ref": "#/components/schemas/EthUint64" }, "removed": { + "description": "Indicates whether the log was removed due to a chain reorganization.", "type": "boolean" }, "topics": { + "description": "List of topics associated with the event log.", "type": "array", "items": { "$ref": "#/components/schemas/EthHash" } }, "transactionHash": { + "description": "The hash of the RLP message that produced the event log.", "$ref": "#/components/schemas/EthHash" }, "transactionIndex": { + "description": "The index in the tipset of the transaction that produced the event log. The index corresponds to the sequence of messages produced by `ChainGetParentMessages`", "$ref": "#/components/schemas/EthUint64" } } @@ -6487,7 +6661,7 @@ }, "Flags": { "type": "integer", - "format": "uint8", + "format": "uint64", "minimum": 0.0 }, "Key": { @@ -6565,6 +6739,57 @@ } } }, + "F3Instant": { + "description": "represents a particular moment in the progress of GPBFT, captured by instance ID, round and phase.", + "type": "object", + "required": [ + "ID", + "Phase", + "Round" + ], + "properties": { + "ID": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "Phase": { + "type": "integer", + "format": "uint8", + "minimum": 0.0 + }, + "Round": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } + }, + "F3Participant": { + "type": "object", + "required": [ + "FromInstance", + "MinerID", + "ValidityTerm" + ], + "properties": { + "FromInstance": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "MinerID": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "ValidityTerm": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } + }, "F3PowerEntry": { "description": "PowerEntry represents a single entry in the PowerTable, including ActorID and its StoragePower and PubKey.", "type": "object", @@ -8206,4 +8431,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/test-suite/src/tests.rs b/src/test-suite/src/tests.rs index d157482..c902f19 100644 --- a/src/test-suite/src/tests.rs +++ b/src/test-suite/src/tests.rs @@ -8,9 +8,15 @@ //! //! Tests are free to [`panic!`], [`assert!`], [`fail!`], or [propogate errors](crate::harness::Context). +use std::str::FromStr; + pub use crate::harness::prelude::*; pub use assert2::assert; +use bindings::v1::{ + BlockHash, BlockNumber, BlockNumberOrHash, EthAddress, EthBigInt, EthBytes, EthCallMessage, + EthHash, EthInt64, EthUint64, FilterId, +}; use num_bigint::BigUint; use num_traits::Num; @@ -38,6 +44,7 @@ pub fn all() -> Vec> { [Tag::SchemaCoverage], |client| { let number = client.Filecoin_EthBlockNumber()?; + // TODO(elmattic): use pattern instead assert!( is_hex_string(&number), "a block number should be an hexadecimal string" @@ -45,6 +52,192 @@ pub fn all() -> Vec> { Ok(()) }, ), + // v1::none( + // "EthBlockNumber with no authorization token", + // [Tag::SchemaCoverage], + // |client| { + // let block = client.Filecoin_EthGetBlockByNumber( + // &BlockNumberOrHash { + // subtype_0: None, + // subtype_1: None, + // subtype_2: None, + // subtype_3: Some(BlockNumber { + // block_number: EthInt64("0x1FFBDF".into()), + // }), + // subtype_4: None, + // }, + // true, + // )?; + // Ok(()) + // }, + // ), + v1::none( + "EthAccounts with no authorization token", + [Tag::SchemaCoverage], + |client| { + let _accounts = client.Filecoin_EthAccounts()?; + Ok(()) + }, + ), + v1::none( + "EthChainId with no authorization token", + [Tag::SchemaCoverage], + |client| { + let _id = client.Filecoin_EthChainId()?; + Ok(()) + }, + ), + v1::none( + "EthGasPrice with no authorization token", + [Tag::SchemaCoverage], + |client| { + let _price = client.Filecoin_EthGasPrice()?; + Ok(()) + }, + ), + v1::none( + "EthProtocolVersion with no authorization token", + [Tag::SchemaCoverage], + |client| { + let _version = client.Filecoin_EthProtocolVersion()?; + Ok(()) + }, + ), + v1::none( + "EthNewPendingTransactionFilter with no authorization token", + [Tag::SchemaCoverage], + |client| { + let _version = client.Filecoin_EthNewPendingTransactionFilter()?; + Ok(()) + }, + ), + v1::none( + "EthNewBlockFilter with no authorization token", + [Tag::SchemaCoverage], + |client| { + let _vfilter = client.Filecoin_EthNewBlockFilter()?; + Ok(()) + }, + ), + v1::none( + "EthAddressToFilecoinAddress with no authorization token", + [Tag::SchemaCoverage], + |client| { + let _address = client.Filecoin_EthAddressToFilecoinAddress(&EthAddress::from_str( + "0xff38c072f286e3b20b3954ca9f99c05fbecc64aa", + ) + .unwrap())?; + Ok(()) + }, + ), + v1::none( + "EthSyncing with no authorization token", + [Tag::SchemaCoverage], + |client| { + let _result = client.Filecoin_EthSyncing()?; + Ok(()) + }, + ), + // v1::none( + // "EthGetBalance with no authorization token and subtype_1", + // [Tag::SchemaCoverage], + // |client| { + // let _balance = client.Filecoin_EthGetBalance( + // &EthAddress::from_str("0x6cb414224f0b91de5c3b616e700e34a5172c149f").unwrap(), + // &BlockNumberOrHash { + // subtype_0: None, + // subtype_1: Some(EthInt64("0x219153".into())), + // subtype_2: None, + // subtype_3: None, + // subtype_4: None, + // }, + // )?; + // Ok(()) + // }, + // ), + // v1::none( + // "EthGetBalance with no authorization token and subtype_2", + // [Tag::SchemaCoverage], + // |client| { + // let _balance = client.Filecoin_EthGetBalance( + // &EthAddress::from_str("0x6cb414224f0b91de5c3b616e700e34a5172c149f").unwrap(), + // &BlockNumberOrHash { + // subtype_0: None, + // subtype_1: None, + // subtype_2: Some(EthHash("0x711da3a3ebc8fdfea3427d0d7b14e55b94f354baf33a93adca658b28e333f133".into())), + // subtype_3: None, + // subtype_4: None, + // }, + // )?; + // Ok(()) + // }, + // ), + v1::none( + "EthGetBalance with no authorization token and subtype_3", + [Tag::SchemaCoverage], + |client| { + let _balance = client.Filecoin_EthGetBalance( + &EthAddress::from_str("0x6cb414224f0b91de5c3b616e700e34a5172c149f").unwrap(), + &BlockNumberOrHash { + subtype_0: None, + subtype_1: None, + subtype_2: None, + subtype_3: Some(BlockNumber { + block_number: EthInt64("0x219153".into()), + }), + subtype_4: None, + }, + )?; + Ok(()) + }, + ), + v1::none( + "EthGetBalance with no authorization token and subtype_4", + [Tag::SchemaCoverage], + |client| { + let _balance = client.Filecoin_EthGetBalance( + &EthAddress::from_str("0x6cb414224f0b91de5c3b616e700e34a5172c149f").unwrap(), + &BlockNumberOrHash { + subtype_0: None, + subtype_1: None, + subtype_2: None, + subtype_3: None, + subtype_4: Some(BlockHash { + block_hash: EthHash("0x711da3a3ebc8fdfea3427d0d7b14e55b94f354baf33a93adca658b28e333f133".into()), + require_canonical: false, + }), + }, + )?; + Ok(()) + }, + ), + // v1::none( + // "EthCall with no authorization token", + // [Tag::SchemaCoverage], + // |client| { + // let balance = client.Filecoin_EthCall(&EthCallMessage { + // data: + // EthBytes { 0: "0xf8b2cb4f000000000000000000000000CbfF24DED1CE6B53712078759233Ac8f91ea71B6" + // .into() } , + // from: None, + // gas: EthUint64 { 0: "0x0".into() }, + // gas_price: EthBigInt { 0: "0x0".into() }, + // to: Some( + // EthAddress::from_str("0x0c1d86d34e469770339b53613f3a2343accd62cb").unwrap(), + // ), + // value: EthBigInt { 0: "0x0".into() }, + // }, & BlockNumberOrHash { + // subtype_0: Some("latest".into()), + // subtype_1: None, + // subtype_2: None, + // subtype_3: None, + // subtype_4: None, + // }, + // )?; + // dbg!(&balance); + // Ok(()) + // }, + // ), ] .into() }