Class: Counterparty::TxEncode

Inherits:
Object
  • Object
show all
Defined in:
lib/counterparty/tx_encode.rb

Defined Under Namespace

Classes: DataTooLarge, InvalidPubkey, InvalidPubkeyGenerated, MissingPubkey, MissingSenderAddr

Constant Summary collapse

PREFIX =
'CNTRPRTY'
P2PKH =
'OP_DUP OP_HASH160 %s OP_EQUALVERIFY OP_CHECKSIG'
MULTISIG =
'1 %s %s OP_CHECKMULTISIG'
OPRETURN =
'OP_RETURN %s'
BYTES_IN_MULTISIG =

33 is the size of a pubkey, there are two pubkeys in a multisig, 1 byte is lost for the data length byte, and two bytes are lost on each key for the data_to_pubkey inefficiency

(33 * 2) - 1 - 2 - 2
BYTES_IN_PUBKEYHASH =
20 - 1
BYTES_IN_OPRETURN =
40

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(encrypt_key, source_data, options = {}) ⇒ TxEncode

Returns a new instance of TxEncode.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/counterparty/tx_encode.rb', line 29

def initialize(encrypt_key, source_data, options = {})
  @source_data, @encrypt_key = source_data, encrypt_key

  if options[:sender_pubkey]
    @sender_pubkey = options[:sender_pubkey]
    @sender_addr = Bitcoin.pubkey_to_address(sender_pubkey)
  elsif options.has_key? :sender_addr
    @sender_addr = options[:sender_addr]
  else
    raise MissingSenderAddr
  end

  @receiver_addr = options[:receiver_addr] if options.has_key? :receiver_addr

  @prefix = options[:prefix] || PREFIX
end

Instance Attribute Details

#encrypt_keyObject

Returns the value of attribute encrypt_key.



26
27
28
# File 'lib/counterparty/tx_encode.rb', line 26

def encrypt_key
  @encrypt_key
end

#prefixObject

Returns the value of attribute prefix.



26
27
28
# File 'lib/counterparty/tx_encode.rb', line 26

def prefix
  @prefix
end

#receiver_addrObject

Returns the value of attribute receiver_addr.



26
27
28
# File 'lib/counterparty/tx_encode.rb', line 26

def receiver_addr
  @receiver_addr
end

#sender_addrObject

Returns the value of attribute sender_addr.



26
27
28
# File 'lib/counterparty/tx_encode.rb', line 26

def sender_addr
  @sender_addr
end

#sender_pubkeyObject

Returns the value of attribute sender_pubkey.



26
27
28
# File 'lib/counterparty/tx_encode.rb', line 26

def sender_pubkey
  @sender_pubkey
end

#source_dataObject

Returns the value of attribute source_data.



26
27
28
# File 'lib/counterparty/tx_encode.rb', line 26

def source_data
  @source_data
end

Instance Method Details

#encrypt(chunk) ⇒ Object



83
84
85
# File 'lib/counterparty/tx_encode.rb', line 83

def encrypt(chunk)
  RC4.new(encrypt_key).encrypt chunk
end

#to_opmultisigObject

Raises:



46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/counterparty/tx_encode.rb', line 46

def to_opmultisig
  raise MissingPubkey unless sender_pubkey

  data_length = BYTES_IN_MULTISIG-prefix.length
  p2pkh_wrap collect_chunks(source_data,data_length){|chunk| 
    padding = 0.chr * (data_length-chunk.length)

    data = encrypt [(chunk.length+prefix.length).chr,prefix, chunk, padding].join

    data_keys = [(0...31), (31...62)].collect{|r| data_to_pubkey data[r] }

    MULTISIG % [(data_keys + [sender_pubkey]).join(' '), 3]
  }
end

#to_opreturnObject

Raises:



73
74
75
76
77
78
79
80
81
# File 'lib/counterparty/tx_encode.rb', line 73

def to_opreturn
  # I'm fairly certain that using more than one OP_RETURN per transaction is
  # unstandard behavior right now
  raise DataTooLarge if (source_data.length + prefix.length) > BYTES_IN_OPRETURN

  data = encrypt [prefix,source_data].join

  p2pkh_wrap( OPRETURN % data.unpack('H*').first )
end

#to_pubkeyhashObject



61
62
63
64
65
66
67
68
69
70
71
# File 'lib/counterparty/tx_encode.rb', line 61

def to_pubkeyhash
  p2pkh_wrap collect_chunks(source_data, BYTES_IN_PUBKEYHASH-prefix.length){ |chunk|
    data_length = prefix.length + chunk.length

    padding = 0.chr * (BYTES_IN_PUBKEYHASH - data_length)

    enc_chunk = encrypt [(data_length).chr, prefix, chunk, padding].join

    P2PKH % enc_chunk.unpack('H*').first
  }
end