Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

Add design proposal for generalized ownership #3216

Closed

Conversation

aeyakovenko
Copy link
Member

@aeyakovenko aeyakovenko commented Mar 11, 2019

Problem

Current implementations of ownership rely on account pubkeys, which cannot be composed across programs.

How these problems manifest in Ethereum. https://medium.com/@kelvinfichter/looking-at-ownership-in-the-evm-6e6914d341d

Summary of Changes

Propose a design for general ownership of countable things, with a mechanism to programatically transfer the ownership based on output from other programs.

CC #3266

@aeyakovenko aeyakovenko changed the title Generalized ownership Add design proposal for generalized ownership Mar 11, 2019
Copy link
Contributor

@garious garious left a comment

Choose a reason for hiding this comment

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

I can't give much feedback on this yet. Need more context on the problem being solved. If it's solving the problem that I think it's solving, I'm surprised not to see monoids mentioned in the proposed solution. Seems like this should be a debate between monoids and semigroups and how a program should expose that functionality to accounts that it is the owner of.

I'd think this proposal can take the form:

Runtime doesn't allow parallel access to "credits" on userdata, because it doesn't know what it means to be a credit on an otherwise opaque data type. To define a credit, we propose programs optionally implement a semigroup interface for accounts it owns. Going one step further, the runtime can also create and initialize these accounts if an identity operation is defined. When used in conjunction, the identity and semigroup operations form a monoid, opening the door for additional runtime optimizations such as the popular MapReduce.

book/src/generalized-ownership.md Show resolved Hide resolved
This design describes generalized ownership of countable items on the Solana
blockchain. The goal of this design is to propose a single general-purpose
program whose state can be used across many different programs to implement
ownership, transfer and programmatic assignment.
Copy link
Contributor

Choose a reason for hiding this comment

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

programmatic?

Copy link
Member Author

Choose a reason for hiding this comment

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

Assignment based on the output of a program? What should you call it?

program whose state can be used across many different programs to implement
ownership, transfer and programmatic assignment.

Many programs in Solana should be able to use a common program similar to
Copy link
Contributor

Choose a reason for hiding this comment

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

"use a common program" -> "define an instruction"?

Copy link
Member Author

Choose a reason for hiding this comment

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

@garious not really define, how about: "reuse the same code and state machine"

book/src/generalized-ownership.md Outdated Show resolved Hide resolved
enum OwnerState {
// the owner identity must provide a valid signature for this pubkey
Unique {
// The actual owner key.
Copy link
Contributor

Choose a reason for hiding this comment

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

"actual owner" is a strange thing to say. Smells of a terminology problem. Is there a "not-actual owner" that's hijacked the term "owner"?

Copy link
Member Author

Choose a reason for hiding this comment

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

Account has an owner, which is the program. Signer, which is the thing that owns the some keypair. The owner of the state which stores these bits, which is irrelevant here. How about token_owner, or unit_owner?

Copy link
Contributor

Choose a reason for hiding this comment

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

I can't help specialize vague terminology. I asked because I can't tell what you're referring to. I need you to spend some time either thinking on the terminology and defining it earlier in this document, or spend more time clarifying the problem statement and have others propose solutions.

### OwnerState::Transfer

* account[0] - RW - The OwnerState.
* account[1] - R - Current owner Pubkey, needs a signature. Doesn’t need an
Copy link
Contributor

Choose a reason for hiding this comment

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

A credit-only account needs a signature?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep, it just needs to show proof of owning the identity. Kind of interesting, since this account doesn’t need an actual balance

Copy link
Contributor

Choose a reason for hiding this comment

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

Personally, I'd accept tokens from anybody giving tokens out - my signature is not required.

@aeyakovenko
Copy link
Member Author

@garious, want to work on this together? It would be nice to split this up into a semi group and a monoid.

@garious
Copy link
Contributor

garious commented Mar 13, 2019

@aeyakovenko, I'd prefer not to work on this until you create an GitHub issue that describes the problem in detail, such that we can prioritize it. It's likely that I'll want to write a design proposal of my own and maybe implement it too. The MapReduce possibility is something that we've been talking about since the earliest days of the project.

@aeyakovenko aeyakovenko mentioned this pull request Apr 15, 2019
@garious garious force-pushed the generalized_ownership branch from 093730f to 983215b Compare May 6, 2019 20:57
wip design

cleanup

zero items

fixup! zero items

fixup! zero items

update

grammarly

put the problem up front

wip
@aeyakovenko aeyakovenko force-pushed the generalized_ownership branch from 983215b to a7c3a51 Compare May 10, 2019 20:24
@aeyakovenko aeyakovenko requested a review from garious May 19, 2019 16:41
@aeyakovenko
Copy link
Member Author

@garious let’s move this forward. Dealing with external settlement depends on this.

@garious
Copy link
Contributor

garious commented May 20, 2019

@aeyakovenko, can you explain how dealing with external settlement depends on this?

@aeyakovenko
Copy link
Member Author

@garious the example in the doc discusses how two external assets get traded by an exchange program. The alternative is a single non-generalized exchange that only understands the tokens and external assets it was initially programmed with.

@garious
Copy link
Contributor

garious commented May 20, 2019

@aeyakovenko, I wonder if the fundamental problem here is in the Token program. It decides what to do based on data in Instruction.data. Instead, what could be in Instruction.data is TokenInstruction::LoadInstructionFromAccount. If so, an "analyst" program would accept a TicTacToe account and use that state to store a TokenInstruction into an account that it owns. The Token program would then load a Transfer instruction and proceed as it normally would. The message would be written as such:

let transfer_ix = token::transfer(42, &carol_id, &dan_id);
let message = Message::new(vec![
    ttt_instruction::move(&alice_id, &game_id, 2, 2),
    system_instruction::create_account(&gambling_greg_id, size_of(transfer_tx)),
    tttanalyst_instruction::when_winner(&gambling_greg_id, &game_id, IS_X, transfer_ix),
    token_instruction::load_instruction_from_account(&gambling_greg_id),
]);

client.send_message(&[&alice_keypair, &gambling_greg_keypair, &carol_keypair]);

@aeyakovenko
Copy link
Member Author

@garious, it needs to lock the tokens from transfer while their are in play. In the design it’s covered as OwnerState::Escrow

@garious
Copy link
Contributor

garious commented May 20, 2019

In fact, that last instruction can be generalized for all programs if recognized by the runtime:

system_instruction::load_instruction_from_account(TOKEN_PROGRAM_ID, &gambling_greg_id)

@aeyakovenko
Copy link
Member Author

aeyakovenko commented May 20, 2019

@garious, ah I see. You are looking at the output of the previous instruction. You can do that with atomics. Configure the token program to payout the result based if an instruction is called with the right keys in the same TX. it doesn’t even need to look at the state, just Succeed.

That doesn’t compose. The token program needs to have those hooks. Everyone implementing a token must add them, since it’s sync for that state transition. I can’t add additional tokens and gamble them in tic-tac-toe against other token programs.

@aeyakovenko
Copy link
Member Author

@garious I don’t see where the chain enforces that the transfer occurs if and only if the winner won

@garious
Copy link
Contributor

garious commented May 22, 2019

@aeyakovenko, yes, that's not obvious. It'd be implemented by this line:

tttanalyst_instruction::when_winner(&gambling_greg_id, &game_id, IS_X, transfer_ix)

What it's saying is that the analyst is analyzing the game_id account to see if X won, and if so, storing transfer_ix in gambling_greg_id, and otherwise storing a no-op.

@garious
Copy link
Contributor

garious commented May 22, 2019

The big limitation in my example is the lack of an escrow account. What's awkward there is that the escrow account would be owned by the token program, whereas the contract controlling them would be held by tttanalyast, which cannot sign a token transfer transaction.

Your suggestion of a predicate language in token is one way to move forward, but feels like a long rabbit hole. I'd rather have token delegate ownership to a program, which is already part of this proposal. Let me think on the possibility of making that delegation the only new feature.

@aeyakovenko
Copy link
Member Author

@garious think there are two ways,

  1. token escrow on (program, instruction, keys)
  2. if the tx executes, the transfer occurs to data held in one of the keys

or

  1. token escrow when an Account::data transitions from 0 to pubkey
  2. when the account is non-zero, the escrow can change the owner to pubkey

@garious
Copy link
Contributor

garious commented May 23, 2019

I don't understand what you're saying there ^^^

Copy link
Contributor

@garious garious left a comment

Choose a reason for hiding this comment

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

I'm not optimistic that I'm going to grok this proposal if only incrementally moved forward in response to my review comments. I think this will either require another brain or a rewrite. If a rewrite, I'd suggest way more content in the problem description and less code in the proposed solution.

The goal of this design is to make the following possible:

In a single program, it should be possible to change and update ownership of
arbitrary units of tokens implemented by other programs.
Copy link
Contributor

Choose a reason for hiding this comment

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

This sentence is unclear - specifically "ownership" and "arbitrary units".


## General idea

For items to have externally countable ownership, they must rely on the external
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks like the first use of "externally countable ownership". What does it mean?


## General idea

For items to have externally countable ownership, they must rely on the external
Copy link
Contributor

Choose a reason for hiding this comment

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

What do you mean by "items" and "units" exactly?

## Generalized owner identity

Using the account's pubkey identity as the asset owner identity means that all
the asset transfer APIs must be re-implemented by the program code.
Copy link
Contributor

Choose a reason for hiding this comment

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

That looks like an overreaching assertion.

Using the account's pubkey identity as the asset owner identity means that all
the asset transfer APIs must be re-implemented by the program code.

The proposed solution is to use a pointer to an owner identity.
Copy link
Contributor

Choose a reason for hiding this comment

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

This is using ambiguous terminology.

```rust,ignore
// This state is owned by the MyTokenState
struct MyTokenState {
// This points to an OwnerState structure that identifies the actual owner
Copy link
Contributor

Choose a reason for hiding this comment

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

actual owner


## Programmatic Transfer of Ownership

Currently, programs have no way to trigger a transfer of ownership. A game of
Copy link
Contributor

Choose a reason for hiding this comment

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

trigger?

## Programmatic Transfer of Ownership

Currently, programs have no way to trigger a transfer of ownership. A game of
TicTacToe has no way to assign a prize to the winner.
Copy link
Contributor

Choose a reason for hiding this comment

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

assign or award?


```rust,ignore
// This state is owned by the Owner program
enum OwnerState {
Copy link
Contributor

Choose a reason for hiding this comment

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

Another definition of OwnerState? Are these progressively more advanced definitions? Perhaps this was all the same OwnerState definition and each field was introduced as a full OwnerState definition?

An offer to trade:

```rust,ignore
Trade {
Copy link
Contributor

Choose a reason for hiding this comment

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

Where is Trade defined?

// This state is owned by the MyTokenState
struct MyTokenState {
// This points to an OwnerState structure that identifies the actual owner
owner: Pubkey,
Copy link
Contributor

Choose a reason for hiding this comment

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

why is a pointer to the OwnerState needed in this struct?

@aeyakovenko
Copy link
Member Author

I am going to split this out into two problems.

  1. generalized ownership
  2. cross program state transitions

@garious
Copy link
Contributor

garious commented Jun 13, 2019

@aeyakovenko, can this be closed in favor of #4603?

@aeyakovenko
Copy link
Member Author

@garious want to file another Issue that captures the problem of delegating scarcity to a Token program? And a way to delegate transfer of ownership to other programs from within the Token program?

@garious
Copy link
Contributor

garious commented Jun 13, 2019

@aeyakovenko, in that model, you don't delegate. It's permissionless. You'd spin up a token to represent some other set of tokens, and then stake and trade with the new token. How about tickets for demos of various usecases you propose? I'm working towards betting on tic-tac-toe outcome with a Token. After that, the other example you give here, of swapping two Tokens. Looking for others?

@garious
Copy link
Contributor

garious commented Jun 13, 2019

@aeyakovenko, sounds like your solution must be addressing more problems than what you've provided. You mentioned splitting this proposal into two earlier. Sounds like we'll need that sooner than later. If so, can you do that with issues instead of PRs?

@garious
Copy link
Contributor

garious commented Aug 12, 2019

@aeyakovenko, this PR is very old and hasn't gotten traction. Can we close it for now?

@aeyakovenko
Copy link
Member Author

aeyakovenko commented Aug 12, 2019

@garious closed. We are moving too slowly for general purpose tokens. Maybe stakes will be the first consumer.

buffalojoec added a commit to buffalojoec/solana that referenced this pull request Nov 8, 2024
* SVM: use lps from `FeeStructure` directly

* SVM: rename `lamports_per_signature` to `blockhash_lamports_per_signature`

* program-runtime: rename `lamports_per_signature` to `blockhash_lamports_per_signature`
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants