kwannoel / urban-octo-carnival

DRAFT REPO: trying out gitlab -> github
Apache License 2.0
1 stars 0 forks source link

Collect user fees #157

Open kwannoel opened 3 years ago

kwannoel commented 3 years ago

In GitLab by @fahree on Mar 22, 2021, 23:46

kwannoel commented 3 years ago

In GitLab by @fahree on Mar 22, 2021, 23:58

changed title from C{-reate contracts that gath-}er fees to C{+ollect us+}er fees

kwannoel commented 3 years ago

In GitLab by @fahree on Mar 22, 2021, 23:58

changed the description

kwannoel commented 3 years ago

In GitLab by @fahree on Mar 22, 2021, 23:58

Before:

After?

What does the plumbing need to do?

Bonus:

kwannoel commented 3 years ago

In GitLab by @fahree on Mar 24, 2021, 04:21

marked this issue as related to #145

kwannoel commented 3 years ago

In GitLab by @ApolloUnicorn on Mar 24, 2021, 04:29

@isd

kwannoel commented 3 years ago

In GitLab by @fahree on Apr 1, 2021, 00:44

assigned to @Akaa

kwannoel commented 3 years ago

In GitLab by @ApolloUnicorn on May 10, 2021, 23:05

unassigned @Akaa

kwannoel commented 3 years ago

In GitLab by @ApolloUnicorn on May 12, 2021, 04:28

assigned to @isd

kwannoel commented 3 years ago

In GitLab by @isd on May 16, 2021, 05:20

Question: is the CREATE2 proxy you refer to something that we already have, or is it something we will have to build/set up?

Per our earlier discussions, this issue should be broken up into smaller tasks. Some possible sub-tasks that I see, some of which correspond to the checkboxes above (each top-level bullet could be its own task):

Gathering statistics is already its own ticket (#145)

Does all this sound reasonable?

kwannoel commented 3 years ago

In GitLab by @isd on May 16, 2021, 05:33

This also might provide useful context in which to implement the global variable support that I punted on in !133; @fahree and I both agreed it made sense to wait until we had something that need it, but that doesn't necessarily have to be the multiple-assets code, and in fact I think I'm going to want this right away as I work on the multiplexing support.

So I think step 1 is to make sure the existing global variables which are per-interaction are allocated inside the merkelized state, rather than with define-consecutive-addresses -- so doing the punted part of the scratch space issue, basically. I think on master this is just deposit and timer-start. Getting that small piece merged will allow us to avoid large merge conflicts with multiple assets.

kwannoel commented 3 years ago

In GitLab by @Akaa on May 16, 2021, 14:32

You have a code that creates contract using CREATE2(EVM Opcode) It should have Interaction ID for say a session. Here, some group may want to settle online e-commerce transaction or game or betting activities. You create an interaction ID and a contract(CREATE2). This is done by one of the participants. The new contract address would be what other participants would use going forward. Contract ADDRESS should be created off-line.

Subsequent interactions by the members of this specific session(group) would be tracked by their Interaction ID. The contract created with CREATE2 would not hold state. Its storage would be routed back to the main code that created it. Here you see the need to have a way to know which CREATE2 contracts is updating state, that's the need of interaction ID(one of them). You can then throw a lot to the storage depending on your design. Even after the CREATE2 contract has closed(self-destroyed), we still have their records.

By having global state variables for Dapps interacting with the contracts we have saved them the cost of creating storage each time they want to close out transaction on-chain. We intend to make some money from this enough. That is part of the fees we collect.

kwannoel commented 3 years ago

In GitLab by @isd on May 17, 2021, 05:08

Actually, looking back at evm-runtime, I think I'm wrong re: globals: we don't need to support general globals, we can move the existing globals that we want to be per-interaction inside the merkelized state trivially, just by putting them after frame@ -- and timer-start is already there.

Intuitively I think brk will also need to go inside the merkelized state, which probably means shuffling around the frame restoration logic, but we can fudge it for now if we choose since we're not actually doing dynamic memory allocation (and I think the logic may be wrong/unimplemented as is, not 100% sure).

kwannoel commented 3 years ago

In GitLab by @isd on May 17, 2021, 06:11

Looks like I am further mistaken, in that deposit doesn't actually need to be merkelized, since it's an ephemeral variable that doesn't outlive the call.

Re: verifying we aren't relying on the VM's balance, the only place I see this used is in the &SELFDESTRUCT helper -- which brings up the fact that we also don't want to ever actually use a SELFDESTRUCT instruction if we're multiplexing contracts, so probably we want to make the debug version the only one, or at least make the condition debug OR multiplexed.

Fixing the balance accounting will be trivial.

kwannoel commented 3 years ago

In GitLab by @isd on May 17, 2021, 06:19

@Akaa, I'm clear on what the use of the CREATE2 opcode is for, what's unclear to me is what exactly @fahree means by "proxy" -- is this a running smart contract that we'll deploy, is it a separate daemon outside the blockchain? Is it something we'll have to implement or is this something that already exists that we just need to hook up to the rest of our code?

kwannoel commented 3 years ago

In GitLab by @isd on May 17, 2021, 06:39

I'm going to open separate issues for sub-tasks as I identify them, #185 being the first.

kwannoel commented 3 years ago

In GitLab by @Akaa on May 17, 2021, 07:23

A proxy (from my understanding) is a contract to be shared by all Dapps that intend to close on-chain transactions. Here, you have two contracts. Once which is shared by all the Dapps. But each Dapp whenever it starts a new interaction creates the second contract via CREATE2. However, this second contract should not have its own storage. Its storage should be routed back to the shared(proxy) contract. Proxy contract uses interaction ID to track each contract and it states. The contract created by CREATE2 is almost like multisig (channel) contract.

Everything is on-chain except creation of contract address.

kwannoel commented 3 years ago

In GitLab by @Akaa on May 17, 2021, 19:21

You don't need deposit. Use CALLDATA, get everything from it.

The proxy contract should be like state machine: 1) Start closing(Create all the states, and they would be indexed with interaction ID). 2) Closing in progress 3) Error in data protocol 4) Other stuff You may combine (1) and (2) into ... Build data protocol that would come out of CALLDATA. Use the header to decide which state to execute.

Transaction contract

Just create something that can do multisig and validation with payout. (Pump changes back to proxy)

Someone can call Transaction contract without going through proxy, but any state change is stored at proxy contract.

kwannoel commented 3 years ago

In GitLab by @fahree on May 17, 2021, 23:35

  1. I wrote several "simple apps" in EVM assembly in simple-apps.ss, including the trivial CREATE2 wrapper, a batching proxy, etc.

  2. I wrote in meta-create2.ss some infrastructure so the CREATE2 wrapper can have the very same address on every EVM network, making contract addresses universal.

I believe that contract from meta-create2 is the one we should be using and following.

kwannoel commented 3 years ago

In GitLab by @fahree on May 17, 2021, 23:37

Note that deposit is a short-lived variable, only valid during the transaction. It should not be part of the persistent merkleized state. timer-start should, and already is.

kwannoel commented 3 years ago

In GitLab by @fahree on May 17, 2021, 23:41

And indeed, we don't want any SELFDESTRUCT in a shared contract, only a variant that would account for the current interaction's balance.

(Also, unless the contract is limited to ERC20s trusted by everybody, we need some protection against untrusted ERC20s; at the minimum, some variable that guards against reentrancy during the commit block that makes transfer CALLs.)

kwannoel commented 3 years ago

In GitLab by @fahree on May 17, 2021, 23:44

@Akaa I admit I don't understand everything you say :-(

@isd If that helps, you can create a Google doc about what needs to be done, that we can comment on.

kwannoel commented 3 years ago

In GitLab by @alex413 on May 18, 2021, 03:36

@fare What's the rough deliverable date for this issue?

kwannoel commented 3 years ago

In GitLab by @isd on May 18, 2021, 04:44

Note that deposit is a short-lived variable, only valid during the transaction. It should not be part of the persistent merkleized state. timer-start should, and already is.

Yeah, I realized this at some point after my first comment, see comment starting with "Looks like I was further mistaken"

@alex413, I think it's a bit too soon to make specific predictions about the overall issue; we need to pin down some details first. Though see my comment on #185.

I made an etherpad doc, contents based on an earlier comment of mine, we can work there:

https://thelibrary.sandcats.io/shared/tbDx2TPtfQ1IAzKsIHm_9CLkROkg1xxeQww8oYvmyyR

kwannoel commented 3 years ago

In GitLab by @isd on May 18, 2021, 05:04

I'm still fuzzy on exactly what the proxy is for; my current understanding is that it is itself a contract that will be invoked to create other contracts, and that somehow this indirection will make gathering statistics easier. But if we're already going to be multiplexing interactions of the same dapp onto one contract, I don't know that I understand why this helps?

kwannoel commented 3 years ago

In GitLab by @isd on May 18, 2021, 05:07

Another subtask that needs to happen to multiplex contracts: right now the addresses for the participants are compiled into the contract itself as constants at e.g. the set-participant call sites. In order to use the same compiler output for multiple interactions, we would need to rework this so that these are supplied when spawning an interaction, and resolved at runtime.

kwannoel commented 3 years ago

In GitLab by @fahree on May 19, 2021, 08:50

If that's what you call the "proxy", the CREATE2 wrapper exists so anyone can create a contract with a fixed address based only on the contract initialization code (plus some agreed-upon salt), so people can use MAST techniques on Ethereum, wherein the agreed upon code is only revealed if needed in case of dispute, whichever the party starting the dispute may be. In the case of shared contracts, that also makes it trivial to determine if the contract was already created: just use eth_getCode on the expected contract address.

(By contrast, contracts created using CREATE depend on the nonce of the creating user, which makes it impossible to detect whether a contract of given content was already created, short of scanning each and every contract ever created on the blockchain.)

Since for now presumably we'll be the only one using this wrapper contract, we can also use it for gathering usage statistics on all contracts created through our infrastructure.

kwannoel commented 3 years ago

In GitLab by @isd on May 23, 2021, 06:10

Another subtask that needs to happen to multiplex contracts: right now the addresses for the participants are compiled into the contract itself as constants at e.g. the set-participant call sites. In order to use the same compiler output for multiple interactions, we would need to rework this so that these are supplied when spawning an interaction, and resolved at runtime.

Actually, I think these are already stored in variables, so that's fine, no change needed.

kwannoel commented 3 years ago

In GitLab by @isd on May 23, 2021, 06:14

So as I understand it, the point of the CREATE2 wrapper is just so that we can be notified when contracts are created using glow. Is that basic statement of purpose correct & complete, or is there more to it than that?

kwannoel commented 3 years ago

In GitLab by @isd on May 23, 2021, 06:18

Minor design point, I think it would simplify things if instead of storing the state digest, we stored the state digest XOR'd with the initial state digest -- this way we don't have to have any kind of explicit "creation" logic for interactions; when the shared contract is created all possible interactions implicitly exist and are in their initial state, since state1 xor state1 = 0

kwannoel commented 3 years ago

In GitLab by @isd on May 29, 2021, 02:04

A caveat to my xor suggestion is, we need to make sure the common state is valid; if participants can specify an arbitrary hash for initial state, they could possibly provide a bogus state that allows them to extract funds that belong to other interactions on the same contract.

So to make that work we probably need to have some split between per-interaction inputs and "static" initial state common to all interactions, and have the interaction prelude verify that the "static" state matches a fixed hash.

So we need to tease apart variables based on which section they belong in.

@fahree, interested in your thoughts (also to my question re: CREATE2).

kwannoel commented 3 years ago

In GitLab by @fahree on May 29, 2021, 04:00

Yeah, that works if the initial state is valid and does not require any deposit (deposits could happen as part of transitioning to the next state).

Beware though that indeed, creating the initial state itself must be done in a way that ensures you cannot fake state for others. So the state dispatcher in the prelude must know how to create interaction state properly.

As for CREATE2, it can also be used to share a contract with everyone who has the same source code + compiler, thus saving in gas for everyone but the initial users (who could be us pre-seeding the contract). But it's also used in e.g. a generalized state channel where you do not know which of the multiple participants will need to create the contract in the future (because the other one fails to cooperate), yet want to know the address in advance.

kwannoel commented 3 years ago

In GitLab by @isd on May 29, 2021, 04:31

Quoting François-René Rideau (@fahree) (2021-05-28 16:00:43)

As for CREATE2, it can also be used to share a contract with everyone who has the same source code + compiler, thus saving in gas for everyone but the initial users (who could be us pre-seeding the contract). But it's also used in e.g. a generalized state channel where you do not know which of the multiple participants will need to create the contract in the future (because the other one fails to cooperate), yet want to know the address in advance.

So, as I understand it there are two things under discussion:

kwannoel commented 3 years ago

In GitLab by @fahree on May 29, 2021, 11:00

The proxy is necessary because the CREATE2 address uses the creator's address as part of the generated contract's address. The proxy contract ensures that this address is a global constant that doesn't depend on the identity of any participant to any action. (And a special setup in meta-create2.ss ensures that the proxy contract itself is at a fixed address across blockchains.)

kwannoel commented 3 years ago

In GitLab by @isd on May 29, 2021, 11:28

Aha! That was the bit I was missing, thanks.

Quoting François-René Rideau (@fahree) (2021-05-28 23:00:21)