Author Topic: How to encode a PTS address?  (Read 4755 times)

0 Members and 1 Guest are viewing this topic.

Offline toast

  • Hero Member
  • *****
  • Posts: 4001
    • View Profile
  • BitShares: nikolai
http://docs.python.org/2/library/hashlib.html#hashlib.hash.update

In that case it looks like

Code: [Select]
ripe160 = hashlib.new('ripemd160')
ripe160.update(h)
d = ripe160.digest()

is just computing ripemd160(h), no?
« Last Edit: January 03, 2014, 09:10:48 pm by toast »
Do not use this post as information for making any important decisions. The only agreements I ever make are informal and non-binding. Take the same precautions as when dealing with a compromised account, scammer, sockpuppet, etc.

Offline 5chdn

  • Sr. Member
  • ****
  • Posts: 487
  • i wonder how many chars i can put in this field 50
    • View Profile
    • Votesapp
  • GitHub: 5chdn
Ok yeah that script seems wrong. Let me try.

Code: [Select]
asm_hash = "your_hash"
extended_hash = "34" + asm_hash
binary_extended_hash = extended_hash.decode("hex")
double_hash = hashlib.sha256(hashlib.sha256(binary_extended_hash))
checksum = double_hash[:3]    # first 4 bytes
binary_address = binary_extended_hash + checksum
pts_address = b58encode(binary_address)

You might have to insert some prints to see make sure I'm converting between strings, hex, and binary correctly, and adjust accordingly. If you put a print after every line and show us the output we can try to help debug.

toast, i really appreciate your help, but the original script is exactly doing what i want. your modified script is encoding correctly the wrong hash.

Code: [Select]
# this is the <sig pupkey> asm hash
script = "304402205e81e8ed0b1f7cf6d1d415961859d3b95f5e5c353af303b6cef1e3efa6c3349702202fa9fdd6914abd0e9606c78899e7f3010cafdad211645cf459ae18b3b827b2c101 0365e0beb9a0c1497f3667067aeb8f3ea9dc4c9d5696cee7f19eae49f9457a5cfb".split()

# this is the extracted pubkey
pub_key = script[1]

# this is the binary pubkey? (why is it called 'decode'?)
binary_pub_key = pub_key.decode("hex")

# thats a sha256 performed on the binary pub key
h = hashlib.sha256(binary_pub_key).digest()

# thats generating a new ripemd160 hash, isnt it?
ripe160 = hashlib.new('ripemd160')

# no idea whats happening here?
ripe160.update(h)

# no idea whats happening here?!?
d = ripe160.digest()

# the d is what I want to get, from here I know!

Offline toast

  • Hero Member
  • *****
  • Posts: 4001
    • View Profile
  • BitShares: nikolai
Ok yeah that script seems wrong. Let me try.

Code: [Select]
asm_hash = "your_hash"
extended_hash = "34" + asm_hash
binary_extended_hash = extended_hash.decode("hex")
double_hash = hashlib.sha256(hashlib.sha256(binary_extended_hash))
checksum = double_hash[:3]    # first 4 bytes
binary_address = binary_extended_hash + checksum
pts_address = b58encode(binary_address)

You might have to insert some prints to see make sure I'm converting between strings, hex, and binary correctly, and adjust accordingly. If you put a print after every line and show us the output we can try to help debug.
Do not use this post as information for making any important decisions. The only agreements I ever make are informal and non-binding. Take the same precautions as when dealing with a compromised account, scammer, sockpuppet, etc.

Offline 5chdn

  • Sr. Member
  • ****
  • Posts: 487
  • i wonder how many chars i can put in this field 50
    • View Profile
    • Votesapp
  • GitHub: 5chdn
Le me know if this helps. I may be able to be more helpful if you go back a few steps and explain where you got your original "ASM hash".

This is the ASM hash in the code below:
Code: [Select]
script[1] = 0365e0beb9a0c1497f3667067aeb8f3ea9dc4c9d5696cee7f19eae49f9457a5cfb
And thats where I'm stuck.
This is where the python code starts, assigning the string to the variable "script". I cut some unimportant stuff.

Code: [Select]
script = "304402205e81e8ed0b1f7cf6d1d415961859d3b95f5e5c353af303b6cef1e3efa6c3349702202fa9fdd6914abd0e9606c78899e7f3010cafdad211645cf459ae18b3b827b2c101 0365e0beb9a0c1497f3667067aeb8f3ea9dc4c9d5696cee7f19eae49f9457a5cfb".split()
h = hashlib.sha256(script[1].decode("hex")).digest()
ripe160 =  hashlib.new('ripemd160')
ripe160.update(h)
d = ripe160.digest()

This just takes the pubkey and assigns ripemd160(sha256(pubkey)) to the variable "d". The rest of the code is pretty easy to match up with the diagram I linked above.

What is h exactly? I wasnt able to reproduce this.

Offline bytemaster

Code: [Select]
namespace bts
{
   pts_address::pts_address()
   {
      memset( addr.data, 0, sizeof(addr.data) );
   }

   pts_address::pts_address( const std::string& base58str )
   {
      std::vector<char> v = fc::from_base58( fc::string(base58str) );
      if( v.size() )
         memcpy( addr.data, v.data(), std::min<size_t>( v.size(), sizeof(addr) ) );

      if( !is_valid() )
      {
         FC_THROW_EXCEPTION( exception, "invalid pts_address ${a}", ("a", base58str) );
      }
   }

   pts_address::pts_address( const fc::ecc::public_key& pub )
   {
       auto dat      = pub.serialize_ecc_point();
       auto sha2     = fc::sha256::hash(dat.data, sizeof(dat) );
       auto rep      = fc::ripemd160::hash((char*)&sha2,sizeof(sha2));
       addr.data[0]  = 56;
       memcpy( addr.data+1, (char*)&rep, sizeof(rep) );
       auto check    = fc::sha256::hash( addr.data, sizeof(rep)+1 );
       check = fc::sha256::hash(check); // double
       memcpy( addr.data+1+sizeof(rep), (char*)&check, 4 );
   }

   /**
    *  Checks the address to verify it has a
    *  valid checksum and prefix.
    */
   bool pts_address::is_valid()const
   {
       if( addr.data[0]  != 56 ) return false;
       auto check    = fc::sha256::hash( addr.data, sizeof(fc::ripemd160)+1 );
       check = fc::sha256::hash(check); // double
       return memcmp( addr.data+1+sizeof(fc::ripemd160), (char*)&check, 4 ) == 0;
   }

   pts_address::operator std::string()const
   {
        return fc::to_base58( addr.data, sizeof(addr) );
   }
}

bitshares/src/pts_address.cpp
For the latest updates checkout my blog: http://bytemaster.bitshares.org
Anything said on these forums does not constitute an intent to create a legal obligation or contract between myself and anyone else.   These are merely my opinions and I reserve the right to change them at any time.

Offline toast

  • Hero Member
  • *****
  • Posts: 4001
    • View Profile
  • BitShares: nikolai
Do not use this post as information for making any important decisions. The only agreements I ever make are informal and non-binding. Take the same precautions as when dealing with a compromised account, scammer, sockpuppet, etc.

Offline toast

  • Hero Member
  • *****
  • Posts: 4001
    • View Profile
  • BitShares: nikolai
Hmm, I noticed he may be applying sha256 an extra time in there, since it's not possible for the script ouput to contain the actual pubkey if the input is sha256(pubkey).

Again, it might be easier if we just try this process from the very start. Are you just manually trying to generate PTS public keys? What's your goal?
Do not use this post as information for making any important decisions. The only agreements I ever make are informal and non-binding. Take the same precautions as when dealing with a compromised account, scammer, sockpuppet, etc.

Offline toast

  • Hero Member
  • *****
  • Posts: 4001
    • View Profile
  • BitShares: nikolai
I'm not sure what you mean by ASM hash. Let me step through the code for you, hopefully you can match up your string to some part of this process.

Code: [Select]
OP_DUP OP_HASH160 496650cdb4b6275ca4478c0ce98cb6f7224bb1e7 OP_EQUALVERIFY OP_CHECKSIG
The string in there is sha256(public_key). This script creates ripemd160(sha256(public_key)), then does some verification on it. The script outputs this string, which is <sig> <pubkey>.

Code: [Select]
304402205e81e8ed0b1f7cf6d1d415961859d3b95f5e5c353af303b6cef1e3efa6c3349702202fa9fdd6914abd0e9606c78899e7f3010cafdad211645cf459ae18b3b827b2c101 0365e0beb9a0c1497f3667067aeb8f3ea9dc4c9d5696cee7f19eae49f9457a5cfb
This is where the python code starts, assigning the string to the variable "script". I cut some unimportant stuff.

Code: [Select]
script = "304402205e81e8ed0b1f7cf6d1d415961859d3b95f5e5c353af303b6cef1e3efa6c3349702202fa9fdd6914abd0e9606c78899e7f3010cafdad211645cf459ae18b3b827b2c101 0365e0beb9a0c1497f3667067aeb8f3ea9dc4c9d5696cee7f19eae49f9457a5cfb".split()
h = hashlib.sha256(script[1].decode("hex")).digest()
ripe160 =  hashlib.new('ripemd160')
ripe160.update(h)
d = ripe160.digest()

This just takes the pubkey and assigns ripemd160(sha256(pubkey)) to the variable "d". The rest of the code is pretty easy to match up with the diagram I linked above.

Code: [Select]
#Prepend the Mainnet prefix
address = ('\x00' + d)
Replace 0x00 with 0x38.
Code: [Select]
#Calculate checksum
checksum = hashlib.sha256(hashlib.sha256(address).digest()).digest()[:4]
# Build the raw address
address += checksum
# Encode the address in base58
encoded_address = b58encode(address)
print encoded_address

Le me know if this helps. I may be able to be more helpful if you go back a few steps and explain where you got your original "ASM hash".
Do not use this post as information for making any important decisions. The only agreements I ever make are informal and non-binding. Take the same precautions as when dealing with a compromised account, scammer, sockpuppet, etc.

Offline 5chdn

  • Sr. Member
  • ****
  • Posts: 487
  • i wonder how many chars i can put in this field 50
    • View Profile
    • Votesapp
  • GitHub: 5chdn
0x38 == 56
Will check it out when I get to a computer

Yep sorry, of course!

Offline toast

  • Hero Member
  • *****
  • Posts: 4001
    • View Profile
  • BitShares: nikolai
0x38 == 56
Will check it out when I get to a computer
Do not use this post as information for making any important decisions. The only agreements I ever make are informal and non-binding. Take the same precautions as when dealing with a compromised account, scammer, sockpuppet, etc.

Offline 5chdn

  • Sr. Member
  • ****
  • Posts: 487
  • i wonder how many chars i can put in this field 50
    • View Profile
    • Votesapp
  • GitHub: 5chdn
Which part of this diagram does your string correspond to?

https://en.bitcoin.it/w/images/en/9/9b/PubKeyToAddr.png

You should be able to follow that diagram, except use 0x38 as the network byte.
Why 38? PTS should be 56?

The ASM hash is not in that diagram. It's difficult.

Look at this post http://bitcoin.stackexchange.com/a/8864/6441
He is doing what I need but I cant interpret his python code, he is showing it as example but not explaining what he is doing or why and where he got the information from...

Offline toast

  • Hero Member
  • *****
  • Posts: 4001
    • View Profile
  • BitShares: nikolai
Which part of this diagram does your string correspond to?

https://en.bitcoin.it/w/images/en/9/9b/PubKeyToAddr.png

You should be able to follow that diagram, except use 0x38 as the network byte.
Do not use this post as information for making any important decisions. The only agreements I ever make are informal and non-binding. Take the same precautions as when dealing with a compromised account, scammer, sockpuppet, etc.

Offline 5chdn

  • Sr. Member
  • ****
  • Posts: 487
  • i wonder how many chars i can put in this field 50
    • View Profile
    • Votesapp
  • GitHub: 5chdn
Hi,

I've taken a raw asm public key string from a transaction and followed this guide to convert it ot a base58 encoded PTS address. But the result does not start with P.... is there anything special about PTS addresses or did I just failed to encode correctly?

Cheers
don

PS, see also http://stackoverflow.com/q/20860641/1260906


The approach above was wrong. Can someone tell me step by step how I can convert the ASM Public Key Hash
Code: [Select]
028401a2e512b1b91b882ee1c9291cd407c10916bf791662f7189c9c805643e51c to a PTS Public Key Address?
« Last Edit: December 31, 2013, 06:04:26 pm by donschoe »