create account

Why Ethereum Classic Transactions Do Not Specify Who They Are From by cseberino

View this thread on: hive.blogpeakd.comecency.com
· @cseberino · (edited)
Why Ethereum Classic Transactions Do Not Specify Who They Are From
![](https://i.imgur.com/1nEVug1.png)

Ethereum Classic (ETC) transactions do not specify sending accounts!  These can nevertheless be determined from the special properties of ETC digital signatures which I will discuss.

# Basics

ETC transactions are digitally signed using the Elliptic Curve Digital Signature Algorithm (ECDSA).  Users generate secret random numbers referred to as *private keys*.  From these, users derive pairs of numbers referred to as *public keys*.  Private keys are used for signing and public keys are used for creating account addresses.  Account addresses are simply the least significant 20 bytes of the Keccak 256 hashes of public keys.

ETC users sign the Keccak 256 hashes of transactions rather than the transactions themselves.  All transactions contain their digital signatures but do not contain public or private keys.

# Code

Here is code to sign hashes as well as extract public keys.  Note that the *v* element in the sign function below is not absolutely necessary.  That is the *recovery identifier*.  Without recovery identifiers, public keys could still be determined to be one of two possibilities:

```
#!/usr/bin/env python3

import random

N  = 115792089237316195423570985008687907852837564279074904382605163141518161494337
P  = 115792089237316195423570985008687907853269984665640564039457584007908834671663
Gx = 55066263022277343669578718895168534326250603453777594175500187360389116729240
Gy = 32670510020758816978083085130507043184471273380659243275938904335757337482424

def invert(number, modulus):
        """
        Finds the inverses of natural numbers.
        """

        inverse = 1
        power   = number
        for e in bin(modulus - 2)[2:][::-1]:
                if int(e):
                        inverse = (inverse * power) % modulus
                power = (power ** 2) % modulus

        return inverse

def add(pair_1, pair_2):
        """
        Finds the sums of two pairs of natural numbers.
        """

        if   pair_1 == [0, 0]:
                sum_ = pair_2
        elif pair_2 == [0, 0]:
                sum_ = pair_1
        else:
                if pair_1 == pair_2:
                        temp = 3 * pair_1[0] ** 2
                        temp = (temp * invert(2 * pair_1[1], P)) % P
                else:
                        temp = pair_2[1] - pair_1[1]
                        temp = (temp * invert(pair_2[0] - pair_1[0], P)) % P
                sum_ = (temp ** 2 - pair_1[0]  - pair_2[0]) % P
                sum_ = [sum_, (temp * (pair_1[0] - sum_) - pair_1[1]) % P]

        return sum_

def multiply(number, pair):
        """
        Finds the products of natural numbers and pairs of natural numbers.
        """

        product = [0, 0]
        power   = pair[:]
        for e in bin(number)[2:][::-1]:
                if int(e):
                        product = add(product, power)
                power = add(power, power)

        return product

def sign(hash_, private_key):
        """
        Signs the hashes of transactions.
        """

        v, r, s = 0, 0, 0
        while (0 in [v, r, s]) or (s > N / 2):
                rand_1 = random.randint(1, N - 1)
                rand_2 = multiply(rand_1, (Gx, Gy))
                v      = 27 + (rand_2[1] % 2)
                r      = rand_2[0] % N
                s      = (invert(rand_1, N) * (hash_ + private_key * r)) % N
        signature = [v, r, s]

        return signature

def extract(signature, hash_):
        """
        Extracts public keys from signatures and hashes.
        """

        x = signature[1]
        y = pow(x ** 3 + 7, (P + 1) // 4, P)
        if not ((signature[0] == 27) ^ (y % 2 != 0)):
                y = P - y
        pair_1     = multiply(N - hash_, (Gx, Gy))
        pair_2     = multiply(signature[2], (x, y))
        public_key = multiply(invert(x, N), add(pair_1, pair_2))

        return public_key
```

# Example

Here is a sample session.  Note that public keys are derived from private keys.  Note also that public keys can be extracted from just digital signatures and hashes:

```
>>> import random

>>> private_key = random.randint(1, N - 1)

>>> private_key
35636539346190372582315692516374242719103073333795075326298350689544837734965

>>> public_key  = multiply(private_key, (Gx, Gy))

>>> public_key
[10757423063503191043103820533877053013000279578405346773342154037103409266674, 7381758142671922835737972540968321852940615069452568240305754718379589332809]

>>> hash_ = 0xf62d00f14db9521c03a39c20e94aa10a82ff5f5a614772b25e36757a95a71048

>>> signature = sign(hash_, private_key)

>>> signature
[27, 98724900145462879751706452062533342220571445052703717184348248131619990530523, 32577540995538717464732386398395311288498952178867441186019143827849301542010]

>>> result = extract(signature, hash_)

>>> result
[10757423063503191043103820533877053013000279578405346773342154037103409266674, 7381758142671922835737972540968321852940615069452568240305754718379589332809]

>>> result == public_key
True
```

# Conclusion

ETC transactions do not specify who they are from but the mathematics of ECDSA reveals a method to find sending account public keys and addresses.  Not explicitly storing this information makes the ETC blockchain smaller.

# Feedback

Feel free to leave any comments or questions below. You can also contact me by email at cs@etcplanet.org or by clicking any of these icons:

![](https://cdn-images-1.medium.com/max/2000/0*eoFC6QOWZ--bCngK.png)

![](https://cdn-images-1.medium.com/max/2000/0*i3CwTFEKUnKYHMf0.png)

![](https://cdn-images-1.medium.com/max/2000/0*HQj6HSHxE7pkIBjk.png)

# Acknowledgements

I would like to thank IOHK (Input Output Hong Kong) for funding this effort.

# License

![](https://cdn-images-1.medium.com/max/2000/0*hocpUZXBcjzNJeQ2.png)

This work is licensed under the Creative Commons Attribution ShareAlike 4.0 International License.
👍  , , ,
properties (23)
authorcseberino
permlinkwhy-ethereum-classic-transactions-do-not-specify-who-they-are-from
categoryethereum-classic
json_metadata{"tags":["ethereum-classic","ethereum","etc","eth","blockchain"],"image":["https://i.imgur.com/1nEVug1.png","https://cdn-images-1.medium.com/max/2000/0*eoFC6QOWZ--bCngK.png","https://cdn-images-1.medium.com/max/2000/0*i3CwTFEKUnKYHMf0.png","https://cdn-images-1.medium.com/max/2000/0*HQj6HSHxE7pkIBjk.png","https://cdn-images-1.medium.com/max/2000/0*hocpUZXBcjzNJeQ2.png"],"app":"steemit/0.1","format":"markdown"}
created2019-01-26 15:43:42
last_update2019-01-27 16:48:51
depth0
children1
last_payout2019-02-02 15:43:42
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length5,897
author_reputation5,161,857,859,658
root_title"Why Ethereum Classic Transactions Do Not Specify Who They Are From"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id78,969,981
net_rshares15,982,069,542
author_curate_reward""
vote details (4)
@steemitboard ·
Congratulations @cseberino! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :

<table><tr><td>https://steemitimages.com/60x70/http://steemitboard.com/@cseberino/posts.png?201901261710</td><td>You published more than 30 posts. Your next target is to reach 40 posts.</td></tr>
</table>

<sub>_[Click here to view your Board](https://steemitboard.com/@cseberino)_</sub>
<sub>_If you no longer want to receive notifications, reply to this comment with the word_ `STOP`</sub>


To support your work, I also upvoted your post!


> Support [SteemitBoard's project](https://steemit.com/@steemitboard)! **[Vote for its witness](https://v2.steemconnect.com/sign/account-witness-vote?witness=steemitboard&approve=1)** and **get one more award**!
properties (22)
authorsteemitboard
permlinksteemitboard-notify-cseberino-20190126t180805000z
categoryethereum-classic
json_metadata{"image":["https://steemitboard.com/img/notify.png"]}
created2019-01-26 18:08:03
last_update2019-01-26 18:08:03
depth1
children0
last_payout2019-02-02 18:08:03
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length796
author_reputation38,975,615,169,260
root_title"Why Ethereum Classic Transactions Do Not Specify Who They Are From"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id78,977,293
net_rshares0