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

ERC 918 - Mineable Token Standard #918

Merged
merged 15 commits into from
Apr 24, 2018
Merged

ERC 918 - Mineable Token Standard #918

merged 15 commits into from
Apr 24, 2018

Conversation

10d9e
Copy link
Contributor

@10d9e 10d9e commented Mar 8, 2018

When opening a pull request to submit a new EIP, please use the suggested template: https://github.com/ethereum/EIPs/blob/master/eip-X.md

@10d9e 10d9e changed the title Create eip-541.md ERC 541 - Mineable Token Standard Mar 8, 2018
@nicksavers nicksavers added the ERC label Mar 8, 2018
EIPS/eip-541.md Outdated
function getMiningDifficulty() public constant returns (uint)
```

#### getMiningReward

Choose a reason for hiding this comment

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

Maybe we should include a getDifficultyAdjustmentPeriod() method as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed

EIPS/eip-541.md Outdated
Returns a flag indicating a successful hash digest verification. In order to prevent MiTM attacks, it is recommended that the digest include a recent ethereum block hash and msg.sender's address. Once verified, the mint function calculates and delivers a mining reward to the sender and performs internal accounting operations on the contract's supply.

``` js
function mint(uint256 nonce, bytes32 challenge_digest) public returns (bool success)

Choose a reason for hiding this comment

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

Suggestion: Allow merge mining by including a new parameter uint256 extraNonce
Reasoning: Merge-mining works by concatenating nonce + extraNonce and then performing PoW on the concatenation. Let's assume extra-nonce is just a piggy-back token. Whenever a modified miner is able to successfully mine a block with the extra-nonce information in it, receives both the original token, as well as the piggyback token.

Example: 0xNamecoin implemented on top of 0xBitcoin. 0xNamecoin information (dns mapping) is hashed and the merkle root is then used as the extraNonce field. If a user running a 0xNamecoin miner successfully runs a mint operation, it recieves 0xNamecoin tokens.

Resources:
https://bitcointalk.org/index.php?topic=1040859.0
https://namecoin.org/docs/faq/
https://github.com/bitcoin/bitcoin/blob/44080a90a29292df96e92f22242785c5040000a1/src/miner.h#L196
http://mmpool.org/main

EIPS/eip-541.md Outdated
```

#### getMiningReward

Choose a reason for hiding this comment

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

new function: getProofOfWork()
Returns a string of the ProofOfWork algorithm being used.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, the document has been updated accordingly.

@Arachnid
Copy link
Contributor

This proposal seems underspecified - I don't think there's enough detail here to implement two different systems that are intercompatible based only on the spec.

It also seems like a terrible idea.

@10d9e
Copy link
Contributor Author

10d9e commented Mar 17, 2018

@Arachnid Can you be more specific please?

@Arachnid
Copy link
Contributor

@jlogelin Regarding my first point, the standard doesn't specify how challenge values and nonces should be combined and hashed, or how the difficulty is interpreted. Based on this spec, I couldn't write a generic miner for EIP918 tokens, or a token implementation I expect existing miners to be compatible with.

Regarding my second point, PoW doesn't seem to serve any value here, except for distributing tokens to the person willing to waste the most electricity.

@antsankov
Copy link

@Arachnid RE: 2nd point. It seems like you assume the PoW in this case has to always be something useless like sha256, etc., couldn't this standard be used as a distribution model for tokens associated with computational work like protein folding or SETI analysis?

@Arachnid
Copy link
Contributor

@antsankov RE: 2nd point. It seems like you assume the PoW in this case has to always be something useless like sha256, etc., couldn't this standard be used as a distribution model for tokens associated with computational work like protein folding or SETI analysis?

This has been suggested in the past for current PoW coins; the issue is that those problems don't tend to be amenable to the needs of PoW: they have to be problems that require a lot of random trial and error to find a solution, which has variable difficulty and can be verified quickly.

@10d9e
Copy link
Contributor Author

10d9e commented Mar 18, 2018

@Arachnid Re: 1st point. The attempt is to standardize on the expected behavior of a Minable Token and preferably not the implementation. So in the case of having a nonce as part of the implementor's interface, it is expected ( though not required ) that it the Mineable Token implementation would use the concept of a nonce and a challenge.
I do see your point - you are correct in saying that this standard is not enough to implement a mining client. It is meant to describe behavior. Theoretically it would be possible to implement a number of different mineable tokens using different hashing schemes ( ok, up to 3 with the EVM ), difficulty adjustments, etc, but this is implementation specific.
I have provided a link to a reference implementation, however I am open to suggestions on how to tease out functionality in a contract interface further. Thanks for your input.

Re: 2nd point - deferring to more philosophical forums around the subject and purpose:
https://www.reddit.com/r/ethereum/comments/84otpt/i_have_researched_and_deployed_a_new_alternative/

@0xbitcoin
Copy link

0xbitcoin commented Mar 20, 2018

Hello Arachnid, I agree on both points. First that it is underspecified and second that it seems like a terrible idea. Here is an updated specification with a little bit more detail but more will need to be added to and this is being worked on:

https://github.com/0xbitcoin/EIP918-Mineable-Token/blob/master/README.md

When you stated that it seems like a terrible idea, I thought so to. In fact, when I first heard of bitcoin and ethereum, I too thought they were terrible ideas. It took took a little bit of a frame of reference to understand why they are actually quite profound.

Yes, proof of work uses electricity. The reason why this is important is hard to realize but most importantly: The cost of electricity used is negligible compared to the cost of corruption and scamming that occurs in the world and that is occuring in the blockchain space. Why do I compare those two? Because if you dont mine tokens using Proof of Work, you distribute them in the form of ICOs from centralized companies. By choosing ICO tokens over PoW mining tokens, you are choosing big corporations and big banks over decentralized technologies akin to bitcoin. Therefore I urge you to think long and hard about this. I know it is a major leap of thought and hard to quantify. However this is very very important because it is decentralizing token projects. This is a way to decentralize token projects so that they are not all centralized.

I will update when the specification is more fleshed out.

@snissn
Copy link

snissn commented Mar 20, 2018

@Arachnid thank you for the feedback on the PR - I put together a short reference implementation in a small number of lines of python for how the 0xbitcoin PoW algorithm works

https://github.com/snissn/0xbitcoinminer-reference-implementation

The key code is this:

def mine(challenge, public_key, difficulty):
  while True:
    nonce = generate_nonce()
    hash1 = int(sha3.keccak_256(challenge+public_key+nonce).hexdigest(), 16)
    if hash1 < difficulty:
      return nonce, hash1

The community has built GPU implementations as well

@10d9e 10d9e changed the title ERC 541 - Mineable Token Standard ERC 918 - Mineable Token Standard Mar 20, 2018
Updated EIP number to reflect PR
@0xbitcoin
Copy link

Hello @jlogelin please update the EIP918 standard proposal with the following:

https://github.com/0xbitcoin/EIP918-Mineable-Token/blob/master/README.md

@Arachnid
Copy link
Contributor

This is a courtesy notice to let you know that the format for EIPs has been modified slightly. If you want your draft merged, you will need to make some small changes to how your EIP is formatted:

  • Frontmatter is now contained between lines with only a triple dash ('---')
  • Headers in the frontmatter are now lowercase.

If your PR is editing an existing EIP rather than creating a new one, this has already been done for you, and you need only rebase your PR.

In addition, a continuous build has been setup, which will check your PR against the rules for EIP formatting automatically once you update your PR. This build ensures all required headers are present, as well as performing a number of other checks.

Please rebase your PR against the latest master, and edit your PR to use the above format for frontmatter. For convenience, here's a sample header you can copy and adapt:

---
eip: <num>
title: <title>
author: <author>
type: [Standards Track|Informational|Meta]
category: [Core|Networking|Interface|ERC] (for type: Standards Track only)
status: Draft
created: <date>
---

10d9e and others added 3 commits March 27, 2018 20:09
Upon review from a wider audience, this commit includes an interface definition of minimum functionality for mined tokens, a more comprehensive abstract contract that defines required behavior for 4 separate internal phases of solution verification, difficulty modification, epoch period updates, and token reward. Additionally added an example mining program and several simple and complex examples are referenced. Included main net deployed implementation contract addresses 0xbitcoin and PoWAdv. Updated new header format per EIP standardization.
@mining-visualizer
Copy link

@Arachnid

Regarding my second point, PoW doesn't seem to serve any value here, except for distributing tokens to the person willing to waste the most electricity.

Words like 'value' and 'waste' are very subjective. And we can't even have a meaningful discussion about what has value and what is wasteful unless we specify which tokens are going to be distributed via this mechanism. I would be willing to bet that if someone decided to distribute a token using this method, and you really wanted those tokens (ie, you attributed a high value to them), you would have a mining rig set up in no time flat. :)

@0xbitcoin
Copy link

0xbitcoin commented Apr 2, 2018

@Arachnid

Furthermore, PoW mined token distribution is the ONLY token distribution method that is resistant to Sybil Attacks. ICOs and airdrops are 100% very vulnerable to sybil attacking. Heres more info:
https://medium.com/@admazzola/all-token-distribution-is-flawed-thats-why-we-need-pow-tokens-8a79b460f0aa

Please let me know if that makes sense or if it does not. I can always elaborate more.

trying to address :
 Incremental build: disabled. Enable with --incremental
      Generating... 
  Liquid Exception: Liquid error (/home/travis/build/ethereum/EIPs/_includes/eiptable.html line 11): comparison of Array with Array failed included in all.html
jekyll 3.6.2 | Error:  Liquid error (/home/travis/build/ethereum/EIPs/_includes/eiptable.html line 11): comparison of Array with Array failed included 
The command "bash -ex .travis-ci.sh" exited with 1.
@snissn
Copy link

snissn commented Apr 19, 2018

@Arachnid @jlogelin @0xbitcoin
A few popular dapp games have expressed interest in making non-fungible tokens distributable to PoW GPU miners as items or characters. Would the standard need to be changed or augmented to allow for non-fungible tokens to be distributed in addition to ERC20 or is it currently compatible?

@10d9e
Copy link
Contributor Author

10d9e commented Apr 19, 2018

@snissn I think the standard is probably ok in this scenario, as it is now decoupled from other token standards. ERC918 defines "mineability" - as such you should be able to attach and combine this behavior to existing contracts, standardized or otherwise. ( note that the current iteration of this draft has removed the ERC20 prerequisite, as it is not really an extension to standardized token exchange ) Consequently, one should be able to use multiple inheritance to develop a mineable NFT as such:

import "./0xBitcoinBase.sol";
import "./ERC721Token.sol";

/* This contract uses proof of work to create and distribute in game assets */
contract MineableGameAsset is ERC721Token, _0xBitcoinBase('Magic Eggs', 'Mineable Magic in game Eggs', 15000, 0, 1, 512) {

	/* Override internal ERC918 _reward function to mint ERC721 token */
	function _reward() internal returns (uint) {
		uint256 newId = super.totalSupply() + 1; // increment by 1
		// TODO: add token state

		// Add ERC721 token 
		addTokenTo(msg.sender, newId);
		emit Transfer(address(0), msg.sender, newId);
		return 1;
	}
}

https://github.com/0xbitcoin/EIP918-Mineable-Token/blob/master/contracts/0xBitcoinBase.sol

https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/token/ERC721/ERC721Token.sol

@torchmike
Copy link

torchmike commented Apr 20, 2018

apologies, sent from the wrong account see snissn below

@snissn
Copy link

snissn commented Apr 20, 2018

@jlogelin that's great! thanks for clarifying that, I haven't had an opportunity to get into fungible tokens yet..

@Arachnid do you still feel the miner is underspecified? The PoW challenge is literally just keccak(challenge, public_key, nonce). The difficulty is exactly like bitcoin's with these definitions:

tokens per day = 4,320,000 x hashrate / (difficulty x 2^22)
Note: this does not factor pool fees. Subtract 15% from the final amount.

Above is based on the hashrate equation:
time to solve a block in seconds = difficulty x 2^22 / hashrate

see https://0x1d00ffff.github.io/0xBTC-Stats/?page=stats&#miningcalculator

10d9e and others added 5 commits April 20, 2018 23:44
Added full Mineable Abstract contract code to illustrate a more behaviourally specific implementation to the relatively general EIP918 interface.
@Arachnid Arachnid merged commit 2913c14 into ethereum:master Apr 24, 2018
Arachnid pushed a commit to Arachnid/EIPs that referenced this pull request May 2, 2018
* Create eip-541.md

* Added proofOfWork and getDifficultyAdjustmentPeriod

* Updated EIP number

Updated EIP number to reflect PR

* Several functional updates

Upon review from a wider audience, this commit includes an interface definition of minimum functionality for mined tokens, a more comprehensive abstract contract that defines required behavior for 4 separate internal phases of solution verification, difficulty modification, epoch period updates, and token reward. Additionally added an example mining program and several simple and complex examples are referenced. Included main net deployed implementation contract addresses 0xbitcoin and PoWAdv. Updated new header format per EIP standardization.

* Attempt at format fix

trying to address :
 Incremental build: disabled. Enable with --incremental
      Generating... 
  Liquid Exception: Liquid error (/home/travis/build/ethereum/EIPs/_includes/eiptable.html line 11): comparison of Array with Array failed included in all.html
jekyll 3.6.2 | Error:  Liquid error (/home/travis/build/ethereum/EIPs/_includes/eiptable.html line 11): comparison of Array with Array failed included 
The command "bash -ex .travis-ci.sh" exited with 1.

* Abstract contract update

Added full Mineable Abstract contract code to illustrate a more behaviourally specific implementation to the relatively general EIP918 interface.
@10d9e 10d9e deleted the patch-1 branch May 10, 2018 23:21
@montyanderson
Copy link

montyanderson commented May 17, 2018

function mint(uint256 nonce, bytes32 challenge_digest) public returns (bool success);

@0xbitcoin, what's the point of passing in challenge_disgest here, only to check it against the resulting hash? It seems like a waste of gas.

@10d9e
Copy link
Contributor Author

10d9e commented May 17, 2018

@montyanderson The challenge_digest is required to validate the challenge against the resulting hash ( via call to keccak256() ) and the current difficulty target on the smart contract. In the case of 0xbitcoin:

function mint(uint256 nonce, bytes32 challenge_digest) public returns (bool success) {
        digest =  keccak256(challengeNumber, msg.sender, nonce );
        //the challenge digest must match the expected
        if (digest != challenge_digest) revert();
        //the digest must be smaller than the target
        if(uint256(digest) > difficulty) revert();

@montyanderson
Copy link

montyanderson commented May 17, 2018

@jlogelin Why is that necessary? Hashes are deterministic: an input of x will always give an output of y.

If their given nonce produces a digest less than target why must we check it against their given digest?

The code below would work just as well.

function mint(uint256 nonce) public returns (bool success) {
        digest =  keccak256(challengeNumber, msg.sender, nonce );
        //the digest must be smaller than the target
        if(uint256(digest) > difficulty) revert();

@10d9e
Copy link
Contributor Author

10d9e commented May 17, 2018

@montyanderson Oh, I see what you are saying...good point. I'll defer that question to @0xbitcoin

@snissn
Copy link

snissn commented May 17, 2018

Hi @montyanderson

It's a very good question, I think the protocol could work fine with the code that you are describing and with the code as described in the 918 standard. I had been wondering the same myself.

One advantage of the code as described in the 918 standard is that when a mint fails ( because a different miner has successfully submitted a valid nonce on the specific challenge before) it's nice to see the challenge in the failed call. Here's one such example https://etherscan.io/tx/0x94199a79ad3a27e992cb30cc1885c11275cd0b97728d3e72d42da24b604abee4

Without the challenge passed in to mint(), it would be hard for the original miner, or a different auditor to construct all of the inputs to the hash. They would need to assume what challenge the miner was working towards, but they couldn't really know.

In this way, the miner declaring what challenge they are working on in the call both makes it easier to tell what is happening, it also prevents them from "getting lucky" and sending a nonce from one challenge to the ethereum network, having a different miner beat them to minting that challenge, and then getting lucky that their mint call also creates a hash lower than the difficulty when using the next challenge.

As I am writing this, I think for this last reason, to prevent a miner from "getting lucky" and having their nonce succeed on the next challenge, the 918 standard is correct in requiring a challenge to be passed in.

@montyanderson
Copy link

montyanderson commented May 17, 2018

@snissn Good point.

It is easier to debug a dodgy miner this way, however I would suggest there are better methods to go about this.

How about another method? A hash(uint nonce) constant function which returns the correct hash, making it easy for miners to test their hashing is working properly.

My concern here is that any extra gas cost is a disincentive to mine a new (yet to be valuable) token.

@montyanderson
Copy link

montyanderson commented May 17, 2018

@snissn On the point of 'getting lucky', the chance of that happening is very low.

The chance a miner could get lucky is exponentially less than one atom in our entire universe.

@10d9e
Copy link
Contributor Author

10d9e commented May 17, 2018

@montyanderson https://www.youtube.com/watch?v=zMRrNY0pxfM ;)

In all seriousness though, from the perspective of a standardized protocol, which describes expected behavior of mineable tokens, your argument sufficiently holds water - passing the challenge_digest to mint is practically redundant.

If you take a closer look at the current Draft, it offers both an ERC918 behavior only interface, as well as an AbstractERC918 contract that provides 4 phases of the mint operation, including _hash, meant to be overridden by implementors. It might make more sense to pull these up into the Interface and make make the hash method public as you suggest. Something like:

contract ERC918 {
    function mint(uint256 nonce) public returns (bool success);
    function merge(uint256 nonce, address[] mineTokens) public returns (bool) { }
    function getAdjustmentInterval() public view returns (uint);
    function getChallengeNumber() public view returns (bytes32);
    function getMiningDifficulty() public view returns (uint);
    function getMiningTarget() public view returns (uint);
    function getMiningReward() public view returns (uint);
    function hash(uint256 nonce) public view returns (bytes32 digest);
    function _reward() internal returns (uint);
    function _epoch() internal returns (uint);
    function _adjustDifficulty() internal returns (uint);
    event Mint(address indexed from, uint reward_amount, uint epochCount, bytes32 newChallengeNumber);
}

Thoughts @montyanderson @snissn @antsankov @0xbitcoin ?

@snissn
Copy link

snissn commented May 17, 2018

@montyanderson, the probably of a successful mint is related to the difficulty in the contract. I think based on the initial difficulty of 1, the probability would be around 1/2^22 (4- while not quite 2^256, it's still a pretty unlikely event. It makes sense to generalize the interface as @jlogelin is indicating.
Also it's possible to create a mineable token with a very low initial difficulty ( the 2^22 setting is a parameter that could be changed).

I still think it's a good idea to have it in the challenge ( and agree it's not necessary).

@montyanderson
Copy link

@snissn Of course! Apologies, I was multitasking.

@montyanderson
Copy link

montyanderson commented May 18, 2018

@jlogelin @0xbitcoin This is not a criticism but a question: what was the reasoning for the bool return on the mint function?

function mint(uint256 nonce, bytes32 challenge_digest) public returns (bool success);

Looking through the 0xbitcoin code, it appears this never gets used.

Instead you run revert() which throws an error - rather than returning false.

            //the challenge digest must match the expected
            if (digest != challenge_digest) revert();

            //the digest must be smaller than the target
            if(uint256(digest) > miningTarget) revert();


            //only allow one reward for each challenge
             bytes32 solution = solutionForChallenge[challengeNumber];
             solutionForChallenge[challengeNumber] = digest;
             if(solution != 0x0) revert();  //prevent the same answer from awarding twice

It's only then used at the end, which ends up being redundant as the function executing without an error only ever returns true.

           return true;
}

@ethereumdegen
Copy link

ethereumdegen commented Jul 2, 2019

@montyanderson without the revert, the other code would still run and would not reverse the state. It absolutely needs to reverse the state or else the contract will not work properly. Returning a boolean is just a formality, indeed it could return nothing but instead returns true. You do not need to handle the 'true' or check for it when you are programmatically minting from another contract, obviously.

Furthermore, challenge_digest is used as an input so that it can be clearly seen that a small number is the 'result', so that you can easily see that a Proof of Work is required. It is not needed mathematically, but also does not waste significantly gas since that uint would need to be instantiated in the method and stored forever in a mapping anyways, as is being done to prevent a solution from being used twice.

@ethereumdegen
Copy link

@Arachnid or someone please update this EIP to 'COMPLETE' from Draft status, or indicate what would need to be done to get to that point. Many many many pieces of software are now using EIP918 standard methods including MVI Token Miner, COSMIC miner, Mikers pool, Token Mining Pool, LiveCoinWatch, https://0xbtc.info, https://0x1d00ffff.github.io/0xBTC-Stats/, FPGA mining firmware, and more.

@ethereumdegen
Copy link

@Arachnid

status: Draft

???

@nateawelch
Copy link
Contributor

@admazzola I suggest you read eip-1 to see next steps. One of the authors must create a PR changing the status to Last Call, which lasts for 2 weeks, after which the author can create a PR to change status to Final which will be merged if there were no issues during the 2 weeks. This EIP seems pretty inactive though, the authors haven't updated in a while.

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

Successfully merging this pull request may close these issues.