Class: RCS::CoinTransaction

Inherits:
Object
  • Object
show all
Defined in:
lib/rcs-common/evidence/money.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id, vds, seed) ⇒ CoinTransaction

Returns a new instance of CoinTransaction.



529
530
531
532
533
534
535
536
537
538
539
540
541
# File 'lib/rcs-common/evidence/money.rb', line 529

def initialize(id, vds, seed)
  @id = id.reverse.unpack("H*").first
  @seed = seed
  @in = []
  @out = []

  tx = parse_tx(vds)

  calculate_tx(tx)

rescue Exception => e
  raise "Cannot parse Transaction: #{e.message}"
end

Instance Attribute Details

#amountObject (readonly)

Returns the value of attribute amount.



527
528
529
# File 'lib/rcs-common/evidence/money.rb', line 527

def amount
  @amount
end

#fromObject (readonly)

Returns the value of attribute from.



527
528
529
# File 'lib/rcs-common/evidence/money.rb', line 527

def from
  @from
end

#idObject (readonly)

Returns the value of attribute id.



527
528
529
# File 'lib/rcs-common/evidence/money.rb', line 527

def id
  @id
end

#inObject (readonly)

Returns the value of attribute in.



527
528
529
# File 'lib/rcs-common/evidence/money.rb', line 527

def in
  @in
end

#outObject (readonly)

Returns the value of attribute out.



527
528
529
# File 'lib/rcs-common/evidence/money.rb', line 527

def out
  @out
end

#timeObject (readonly)

Returns the value of attribute time.



527
528
529
# File 'lib/rcs-common/evidence/money.rb', line 527

def time
  @time
end

#toObject (readonly)

Returns the value of attribute to.



527
528
529
# File 'lib/rcs-common/evidence/money.rb', line 527

def to
  @to
end

#versusObject (readonly)

Returns the value of attribute versus.



527
528
529
# File 'lib/rcs-common/evidence/money.rb', line 527

def versus
  @versus
end

Instance Method Details

#calculate_tx(tx) ⇒ Object



543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
# File 'lib/rcs-common/evidence/money.rb', line 543

def calculate_tx(tx)
  tx['txIn'].each do |t|
    itx = {}
    # search in the previous hash repo
    itx[:prevout_hash] = t['prevout_hash'].reverse.unpack('H*').first
    itx[:prevout_index] = t['prevout_n']
    @in << itx
  end

  tx['txOut'].each do |t|
    next unless t['value']
    value = t['value']/1.0e8

    address = extract_pubkey(t['scriptPubKey'])
    @out << {value: value, address: address} if address
  end

  @time = tx['timeReceived']
  @versus = (tx['fromMe'] == true) ? :out : :in
end

#extract_pubkey(bytes) ⇒ Object



637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
# File 'lib/rcs-common/evidence/money.rb', line 637

def extract_pubkey(bytes)
  # here we should parse the OPCODES and check them, but we are lazy
  # and we fake the full parsing... :)

  address = nil

  case bytes.bytesize
    # TODO: implement other opcodes
    when 132
      # non-generated TxIn transactions push a signature
      # (seventy-something bytes) and then their public key
      # (33 or 65 bytes) onto the stack:
    when 67
      # The Genesis Block, self-payments, and pay-by-IP-address payments look like:
      # 65 BYTES:... CHECKSIG
    when 25
      # Pay-by-Bitcoin-address TxOuts look like:
      # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG
      # [ OP_DUP, OP_HASH160, OP_PUSHDATA4, OP_EQUALVERIFY, OP_CHECKSIG ]
      op_prefix = bytes[0..2]
      op_suffix = bytes[-2..-1]

      if op_prefix.eql? "\x76\xa9\x14".force_encoding('ASCII-8BIT') and
         op_suffix.eql? "\x88\xac".force_encoding('ASCII-8BIT')
        address = B58Encode.hash_160_to_bc_address(bytes[3..-3], @seed)
      end
    when 23
      # BIP16 TxOuts look like:
      # HASH160 20 BYTES:... EQUAL
  end

  return address
rescue
end

#parse_merkle_tx(vds) ⇒ Object



594
595
596
597
598
599
600
601
# File 'lib/rcs-common/evidence/money.rb', line 594

def parse_merkle_tx(vds)
  h = parse_transaction(vds)
  h['hashBlock'] = vds.read_bytes(32)
  n_merkleBranch = vds.read_compact_size
  h['merkleBranch'] = vds.read_bytes(32*n_merkleBranch)
  h['nIndex'] = vds.read_int32
  return h
end

#parse_transaction(vds) ⇒ Object



603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
# File 'lib/rcs-common/evidence/money.rb', line 603

def parse_transaction(vds)
  h = {}
  start_pos = vds.read_cursor
  h['version'] = vds.read_int32

  n_vin = vds.read_compact_size
  h['txIn'] = []
  (1..n_vin).each {  h['txIn'] << parse_TxIn(vds)  }

  n_vout = vds.read_compact_size
  h['txOut'] = []
  (1..n_vout).each { h['txOut'] << parse_TxOut(vds) }

  h['lockTime'] = vds.read_uint32
  h['__data__'] = vds.buffer[start_pos..vds.read_cursor-1]
  return h
end

#parse_tx(vds) ⇒ Object



564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
# File 'lib/rcs-common/evidence/money.rb', line 564

def parse_tx(vds)
  h = parse_merkle_tx(vds)
  n_vtxPrev = vds.read_compact_size
  h['vtxPrev'] = []
  (1..n_vtxPrev).each { h['vtxPrev'] << parse_merkle_tx(vds) }

  h['mapValue'] = {}
  n_mapValue = vds.read_compact_size
  (1..n_mapValue).each do
    key = vds.read_string
    value = vds.read_string
    h['mapValue'][key] = value
  end

  n_orderForm = vds.read_compact_size
  h['orderForm'] = []
  (1..n_orderForm).each do
    first = vds.read_string
    second = vds.read_string
    h['orderForm'] << [first, second]
  end

  h['fTimeReceivedIsTxTime'] = vds.read_uint32
  h['timeReceived'] = vds.read_uint32
  h['fromMe'] = vds.read_boolean
  h['spent'] = vds.read_boolean

  return h
end

#parse_TxIn(vds) ⇒ Object



621
622
623
624
625
626
627
628
# File 'lib/rcs-common/evidence/money.rb', line 621

def parse_TxIn(vds)
  h = {}
  h['prevout_hash'] = vds.read_bytes(32)
  h['prevout_n'] = vds.read_uint32
  h['scriptSig'] = vds.read_bytes(vds.read_compact_size)
  h['sequence'] = vds.read_uint32
  return h
end

#parse_TxOut(vds) ⇒ Object



630
631
632
633
634
635
# File 'lib/rcs-common/evidence/money.rb', line 630

def parse_TxOut(vds)
  h = {}
  h['value'] = vds.read_int64
  h['scriptPubKey'] = vds.read_bytes(vds.read_compact_size)
  return h
end