This repository was archived by the owner on Mar 5, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 58
Add regaccount function #33
Merged
abourget
merged 7 commits into
eoscanada:master
from
EOSArgentina:add-regaccount-function
Aug 30, 2018
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
aa1a1fa
Add regaccount function
elmato 3f99a20
Use same bancor connector weights as in eosio.system v1.1.0+
elmato dcea8ff
- Signed message now includes pubkey and account name
elmato affa81d
Update test scripts
elmato ce094d9
Assert balance is greater than 0.1 EOS
elmato 0e95f99
- Add the ability to set the max amount of EOS the contract is willin…
elmato b1ec32e
Fix test scripts
elmato File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
 | ||
|
||
# Build | ||
|
||
eosiocpp -o eosio.unregd.wast eosio.unregd.cpp | ||
|
||
# Setup | ||
|
||
```./setup.sh``` | ||
|
||
The setup script will install one contract (besides the defaults ones): | ||
|
||
`eosio.unregd` (empty) | ||
|
||
You need to have nodeos running. | ||
|
||
# Dependecies | ||
|
||
```pip install bitcoin --user``` | ||
```pip install requests --user``` | ||
```sudo apt-get install python-pysha3``` | ||
|
||
# Test | ||
|
||
```./test.sh``` | ||
|
||
The test step will: | ||
|
||
0. Generate a new ETH address with a random privkey. | ||
|
||
1. Add the ETH address (`eosio.unregd::add`) and transfers a random amount of | ||
EOS to the `eosio.unregd` contract. | ||
This is to simulate a user that contributed to the ERC20 but | ||
didn't register their EOS pubkey. | ||
|
||
2. Call `eosio.unregd::regaccount` with: | ||
|
||
* A signature for the message "$lib_block_num,$lib_block_prefix" generated with the ETH privkey | ||
* The desired EOS account name (random in this case) | ||
* An EOS pubkey (used to set the active/owner permission) | ||
|
||
4. The function will : | ||
|
||
* Verify that the destination account name is valid | ||
* Verify that the account does not exists | ||
* Extract the pubkey (compressed) from the signature using a message hash composed from the current TX block prefix/num | ||
* Uncompress the pubkey | ||
* Calculate ETH address based on the uncompressed publickey | ||
* Verify that the ETH address exists in eosio.unregd contract | ||
* Find and split the contribution into cpu/net/liquid | ||
* Calculate the amount of EOS to purchase 8k of RAM | ||
* Use the provided EOS key to build the owner/active authority to be used for the account | ||
* Issue to eosio.unregd the necesary EOS to buy 8K of RAM | ||
* Create the desired account | ||
* Buy RAM for the account (8k) | ||
* Delegate bandwith | ||
* Transfer remaining if any (liquid EOS) | ||
* Remove information for the ETH address from the eosio.unregd DB |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// copyright defined in abieos/LICENSE.txt | ||
|
||
#include <algorithm> | ||
#include <array> | ||
#include <stdexcept> | ||
#include <stdint.h> | ||
#include <string> | ||
#include <string_view> | ||
//#include "ripemd160.hpp" | ||
|
||
namespace abieos { | ||
|
||
const char base58_chars[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; | ||
|
||
bool map_initialized = false; | ||
std::array<int8_t, 256> base58_map{{0}}; | ||
auto get_base58_map() { | ||
if(!map_initialized) { | ||
for (unsigned i = 0; i < base58_map.size(); ++i) | ||
base58_map[i] = -1; | ||
for (unsigned i = 0; i < sizeof(base58_chars); ++i) | ||
base58_map[base58_chars[i]] = i; | ||
map_initialized = true; | ||
} | ||
return base58_map; | ||
} | ||
|
||
template <size_t size> | ||
std::array<uint8_t, size> base58_to_binary(std::string_view s) { | ||
std::array<uint8_t, size> result{{0}}; | ||
for (auto& src_digit : s) { | ||
int carry = get_base58_map()[src_digit]; | ||
if (carry < 0) | ||
eosio_assert(0, "invalid base-58 value"); | ||
for (auto& result_byte : result) { | ||
int x = result_byte * 58 + carry; | ||
result_byte = x; | ||
carry = x >> 8; | ||
} | ||
if (carry) | ||
eosio_assert(0, "base-58 value is out of range"); | ||
} | ||
std::reverse(result.begin(), result.end()); | ||
return result; | ||
} | ||
|
||
enum class key_type : uint8_t { | ||
k1 = 0, | ||
r1 = 1, | ||
}; | ||
|
||
struct public_key { | ||
key_type type{}; | ||
std::array<char, 33> data{}; | ||
}; | ||
|
||
|
||
template <typename Key, int suffix_size> | ||
Key string_to_key(std::string_view s, key_type type, const char (&suffix)[suffix_size]) { | ||
static const auto size = std::tuple_size<decltype(Key::data)>::value; | ||
auto whole = base58_to_binary<size + 4>(s); | ||
Key result{type}; | ||
memcpy(result.data.data(), whole.data(), result.data.size()); | ||
return result; | ||
} | ||
|
||
|
||
public_key string_to_public_key(std::string_view s) { | ||
if (s.size() >= 3 && s.substr(0, 3) == "EOS") { | ||
auto whole = base58_to_binary<37>(s.substr(3)); | ||
public_key key{key_type::k1}; | ||
static_assert(whole.size() == key.data.size() + 4, "Error: whole.size() != key.data.size() + 4"); | ||
memcpy(key.data.data(), whole.data(), key.data.size()); | ||
return key; | ||
} else if (s.size() >= 7 && s.substr(0, 7) == "PUB_R1_") { | ||
return string_to_key<public_key>(s.substr(7), key_type::r1, "R1"); | ||
} else { | ||
eosio_assert(0, "unrecognized public key format"); | ||
} | ||
return public_key{}; | ||
} | ||
|
||
} // namespace abieos | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import os | ||
import sys | ||
import json | ||
import time | ||
import requests as req | ||
from datetime import datetime, timedelta | ||
from hashlib import sha256 | ||
from bitcoin import ecdsa_raw_sign, encode_privkey | ||
from tempfile import mktemp | ||
from subprocess import Popen, PIPE | ||
from sha3 import keccak_256 | ||
|
||
def url_for(url): | ||
return 'http://127.0.0.1:8888{0}'.format(url) | ||
|
||
def ref_block(block_id): | ||
block_num = block_id[0:8] | ||
block_prefix = block_id[16:16+8] | ||
|
||
ref_block_num = int(block_num,16) | ||
ref_block_prefix = int("".join(reversed([block_prefix[i:i+2] for i in range(0, len(block_prefix), 2)])),16) | ||
|
||
return ref_block_num, ref_block_prefix | ||
|
||
if len(sys.argv) < 3: | ||
print "claim.py ETHPRIV EOSACCOUNT" | ||
print " ETHPRIV : Ethereum private key. (can be in Wif or hex format)" | ||
print " EOSACCOUNT: Desired EOS account name" | ||
sys.exit(1) | ||
|
||
block_id = req.get(url_for('/v1/chain/get_info')).json()['last_irreversible_block_id'] | ||
|
||
ref_block_num, ref_block_prefix = ref_block( block_id ) | ||
|
||
priv = sys.argv[1] | ||
eos_account = sys.argv[2] | ||
eos_pub = sys.argv[3] | ||
|
||
msg = '%d,%d,%s,%s' % (ref_block_num, ref_block_prefix, eos_pub, eos_account) | ||
msg = '%s%s%d%s' % ("\x19", "Ethereum Signed Message:\n", len(msg), msg) | ||
|
||
msghash = keccak_256(msg).digest() | ||
# sys.stderr.write("HASH----\n") | ||
# sys.stderr.write(msghash.encode('hex')+"\n") | ||
|
||
v, r, s = ecdsa_raw_sign(msghash, encode_privkey(priv,'hex').decode('hex')) | ||
signature = '00%x%x%x' % (v,r,s) | ||
# sys.stderr.write("SIG----\n") | ||
# sys.stderr.write(signature+"\n") | ||
|
||
binargs = req.post(url_for('/v1/chain/abi_json_to_bin'),json.dumps({ | ||
"code" : "eosio.unregd", | ||
"action" : "regaccount", | ||
"args" : { | ||
"signature" : signature, | ||
"account" : eos_account, | ||
"eos_pubkey" : eos_pub | ||
} | ||
})).json()['binargs'] | ||
|
||
tx_json = """ | ||
{ | ||
"expiration": "%s", | ||
"ref_block_num": %d, | ||
"ref_block_prefix": %d, | ||
"max_net_usage_words": 0, | ||
"max_cpu_usage_ms": 0, | ||
"delay_sec": 0, | ||
"context_free_actions": [], | ||
"actions": [{ | ||
"account": "eosio.unregd", | ||
"name": "regaccount", | ||
"authorization": [{ | ||
"actor": "%s", | ||
"permission": "active" | ||
} | ||
], | ||
"data": %s | ||
} | ||
], | ||
"transaction_extensions": [], | ||
"signatures": [], | ||
"context_free_data": [] | ||
} | ||
""" % ( | ||
(datetime.utcnow() + timedelta(minutes=3)).strftime("%Y-%m-%dT%T"), | ||
ref_block_num, | ||
ref_block_prefix, | ||
"thisisatesta", | ||
binargs | ||
) | ||
|
||
tmpf = mktemp() | ||
with open(tmpf,"w") as f: | ||
f.write(tx_json) | ||
|
||
with open(os.devnull, 'w') as devnull: | ||
cmd = ["cleos","sign","-p","-k","5JNxyTXH4Uu4nxfBG97aQKoKYxTcmeyGjqds5LHHNh88xCTjSTw",tmpf] | ||
p = Popen(cmd, stdout=PIPE, stderr=devnull) | ||
output, err = p.communicate("") | ||
|
||
if p.returncode: | ||
sys.exit(1) | ||
|
||
with open(tmpf,"w") as f: | ||
f.write(output) | ||
|
||
print tmpf | ||
sys.exit(0) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this message is insufficient. Unless I've missed some other secure commitment to it, this allows an attacker to copy the signature parameter and use the same LIB/tapos information to forge a competing claim that would route funds to a different account and/or eos-pubkey.
at a minimum this message should include the eos-pubkey. I think it should include the account name as well but so long as the rightful owner has control that is less of an issue.