Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Standardisation of Events Returned by the Universal Node #21

Open
AlexRipoll opened this issue Nov 14, 2023 · 4 comments
Open

Standardisation of Events Returned by the Universal Node #21

AlexRipoll opened this issue Nov 14, 2023 · 4 comments

Comments

@AlexRipoll
Copy link
Contributor

AlexRipoll commented Nov 14, 2023

Description

When transaction logs are requested from the Universal Node (uNode), the following behaviour is expected:

  • any query about contracts that are not identified as UniversalERC721 must be directly bypassed, routed straight to the underlying Ownership Chain,
  • any query about contract identified as UniversalER721 must include the minting and evolution events that are produced within transactions in the Evochain.

The latter events must be included following the standards:

Events are just returned as part of the queries, they are by no means included in the storage of the Ownership Chain.

This specification is essentially many-to-one: Evochain events must be included for every UniversalERC721 contract in the Ownership Chain whose Universal Location points to the same Evochain collection

Specification

The table below lists the fields of the Event structure, provides descriptions of their intended uses, and specifies the construction of values for the mint and evolve cases as previously outlined.

Key Description Proposed Values for events included from Evochain
removed true: The log was removed due to a chain reorganization. false: Valid log. Same as original in the Evochain
transactionIndex Hex value representing the TX index position from which the log was created. null when the log is pending. TXs from the Evochain are appended at the end of the TXs already present in the Ownership Chain block. If there are more than 1 TX to included, they preserve the relative order from the Evochain. This fully specifies the assigned transactionIndex.
logIndex Hex value representing the log index position in the block. null when the log is pending. log index following the included events a follows from the order in which TXs from the Evochain are included, specified by transactionIndex
transactionHash 32-byte hash of the transaction from which the log was created. null when the log is pending. Original transactionHash from the Evochain - This allows users to locate the transaction in the Evochain
blockHash 32-byte hash of the block where the log was recorded. null when the log is pending. Original unmodified hash of the Ownership Chain block in which the events are included
blockNumber Block number where the log was recorded. null when the log is pending. Block number of the Ownership Chain in which the events are included, as determined by the mapping function defined below.
address 20-byte address from which the log originated. The address of the Universal ERC721 contract in the Ownership Chain.
data Contains one or more 32-byte non-indexed arguments of the log. For mint: null (0x), since all args in the Transfer event are indexed. For evolve, the non-indexed uint256 tokenId arg of MetadataUpdate.
topics An array of indexed log arguments, each 32 bytes. The first topic is the hash of the signature of the event, except when declared with the anonymous specifier. Topics[0] is the hash of the signature of the event: for a mint the value of a Transfer (0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef). For an evolve, the value of a MetadataUpdate (0xf8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7). Finally, for a mint the rest of topics 1,...,3 include the 3 indexed arguments of the event (from, to, tokenId).

Determination of blockNumber in Ownership Chain

Events from TXs produced in the Evochain will be returned as part of the queries for events from Universal ERC721 contracts in the Ownership Chain. The Ownership Chain blockNumber will be determined by comparison of timestamps between both chains. Even if clocks and timestamps are, of course, completely independent in both chains, the mapping must be deterministic.

The mapping returns Evochain events as part of the next block produced in the Ownership Chain, where next is derived from timestamp comparison. The specified mapping has the following properties:

  • It is bounded from below by the blockNumber at which the Universal ERC721 contract was deployed. It therefore prevents events from being included before the contract was created.
  • It is bounded from above by the next-block-to-be-produced by the Ownership Chain, in which case, the uNode must not include the event.
  • In cases where events were produced in the Evochain before the Universal ERC721 contract was deployed, then all those events will be included at the end of the same Ownership Chain block as the contract deployment.

The following pseudocode serves as reference. Any implementation must produce the same results.

// evoTimestamp is the timestamp of the evochain block where the processed event was included
// ownTimestamps is an array: ownTimestamps[n] returns the timestamp of an ownershipChain blocknumber n

function ownChainBlockNumber(uint evoTimestamp, uint[] ownTimestamps) {
	uint n = ownershipContractCreationBlocknumber;
	while (n <= lastProducedOwnchainBlocknumber) {
		if (ownTimestamps[n] > evoTimestamp) return n;
		n++;
	}
	return n;
}

Event Arguments

The following table provides details on the determination of the arguments in the included events.

Evochain Event Universal Node event
MintedWithExternalURI(address indexed to, uint96 slot, uint256 indexed tokenId, string tokenURI) Transfer (index_topic_1 address 0, index_topic_2 address to, index_topic_3 uint256 tokenId)
EvolvedWithExternalURI(uint256 indexed tokenId, string tokenURI) MetadataUpdate(uint256 tokenId)
NewCollection(address indexed owner, address collectionAddress) N/A - This event will not be included by the uNode
@gerardcolomerFV
Copy link
Contributor

gerardcolomerFV commented Nov 15, 2023

Blocknumber proposal

In blockchains where the time between block production is known, knowing the timestamp of the 1st block you can easily deduct all the timestamps for different blocks.
In the first cases where the universalnode is used, both ownership and evolutionchain should follow that pattern.

Option 1

This proposal is to have theEvochain events be related to the latest block that was already produced in that timestamp in the ownership chain.
The main reason in order to take this approach is that, while the blockchain is producing blocks, you can always know to which ownership block a current event emitted in the evochain is related to and add it there.
A problem that this approach has is that you might ask information from the latest block to the universal node that might not be completed with all the evochain information and that might change in a few seconds.

Option 2

This proposal is to have theEvochain events be related to the next block that was produced in that timestamp in the ownership chain.
The main reason in order to take this approach is that when a new ownershipchain block is produced, it will already have all the events of the evochain inside.
A problem that this approach has is that despite some events will be happening in the evochain, the universal node will not be able to add them until a new ownershipchain block is produced.

I believe option 2 is better since this way all the information that you get when you get when you ask for an ownershipchain block to the universal node will always be completed with the evochain information.

Examples

image

Option 1
In this proposal, we argue to always round the evolution chain block to the nearest ownership block that happened BEFORE.
In the previous example:
- The blocks 6 and 7 from the evochain would be related to the block 102 from the ownership chain.
- The range between [101-103] from the ownership chain will be translated to the range between [3-10] from the evolutionchain.

Option 2
In this proposal, we argue to always round the evolution chain block to the nearest ownership block that happened AFTER.
In the previous example:
- The blocks 6 and 7 from the evochain would be related to the block 103 from the ownership chain.
- The range between [101-103] from the ownership chain will be translated to the range between [1-7] from the evolutionchain.

@tonimateos
Copy link
Contributor

tonimateos commented Nov 15, 2023

Proposed improvements:

  1. Nomenclature: change "transformed events" to "included events" everywhere.

  2. Add to the intro: "This specification is essentially many-to-one. It must include evoChain events for every ownership contract that points to those events. The mapping is many-to-one.

  3. Add to the intro: "Currently, there is only support for 2 types of events from the Evochain: mint & evolve". A mint must produce an ERC721 Transfer event from the null address, and an evolve must produce a MetadataUpdate event as specified by ERC4096.

  4. transactionIndex: change the current sentence to: "the transaction from the evochain is appended as the last transaction in the block, which fixes the transactionIndex". Remove any reference to "events" in this row, since they are not relevant

  5. Blockhash: clarify by rephrasing to: "original unmodified hash of the ownership chain block where the events are included"

  6. BlockNumber: clarify by rephrasing to: "Block number of the ownership chain determined by the mapping function defined below"

  7. data: clarify by specifying at the end. "Data payload with the non indexed arguments from the ERC721 event. For Mints, this field is null (0x) since all args in the Transfer event are indexed. For a change in URI, the event is MetadataUpdate.

  8. topics. Make more explicit: "As mandatory, Topics[0] is the hash of the signature of the event. For a mint event, which translates to an ERC721 Transfer event, the value must be 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. For a MetadataUpdate event, the value must be: TODO-ADD"

  9. Add this formula as pseudocode. Any different implementation must be return the same values. It has the following properties:

  • it effectively clamps evoChain events to the nearest-from-below block in the ownChain
  • it prevents events to be included before the contract was created,
  • it prevents processing evoChain events and having to include them in the next block yet to be produced by the ownChain, which would lead to indeterminate index values, or it would force the processing to wait.
// evoTimestamp is the timestamp of the evochain block where the event to be included what included
// ownTimestamps is an array: ownTimestamps[n] returns the timestamp of an ownershipChain blocknumber n

function ownChainBlockNumber(uint evoTimestamp, uint[] ownTimestamps) {
	uint n = ownershipContractCreationBlocknumber;
	while (n < lastProducedOwnchainBlocknumber) {
		if (ownTimestamps[n+1] > evoTimestamp) return n;
		n++;
	}
	return n;
}

@tonimateos
Copy link
Contributor

Please reconsider the sentence under "Considerations". The inclusion, or lack of inclusion, of that event, and other evochain events, is completely unrelated to the order in which things happen.

Also, please apply chatGPT for corrections in grammar and to make several sentences more concise. One example: "This table pretends to explain how each evochain event will be included to a standard ERC721 event" ==> "This table intends to explain how each evochain event will be mapped to a standard ERC721 event".

@tonimateos
Copy link
Contributor

I also suggest to change the name of this issue, so that it becomes simply the place where people come to find the spec, now that there's nothing else to clarify.

@tonimateos tonimateos changed the title Clarification and Standardization of Event Log Values Returned by EVM Node Standardisation of Events Returned by EVM Node Nov 17, 2023
@tonimateos tonimateos changed the title Standardisation of Events Returned by EVM Node Standardisation of Events Returned by the Universal Node Nov 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants