class ArkEcosystem::Crypto::Transactions::Transaction

The model of a transaction.

Attributes

amount[RW]
asset[RW]
expiration[RW]
fee[RW]
id[RW]
network[RW]
recipient_id[RW]
second_signature[RW]
sender_public_key[RW]
sign_signature[RW]
signature[RW]
signatures[RW]
timelock[RW]
timelocktype[RW]
timestamp[RW]
type[RW]
vendor_field[RW]
vendor_field_hex[RW]
version[RW]

Public Class Methods

new() click to toggle source
# File lib/arkecosystem/crypto/transactions/transaction.rb, line 12
def initialize
  @asset = {}
end

Public Instance Methods

deserialize(serialized) click to toggle source
# File lib/arkecosystem/crypto/transactions/transaction.rb, line 163
def deserialize(serialized)
  ArkEcosystem::Crypto::Transactions::Deserializer.new(serialized).deserialize
end
get_id() click to toggle source
# File lib/arkecosystem/crypto/transactions/transaction.rb, line 16
def get_id
  Digest::SHA256.digest(to_bytes(false, false)).unpack('H*').first
end
parse_signatures(serialized, start_offset) click to toggle source
# File lib/arkecosystem/crypto/transactions/transaction.rb, line 97
def parse_signatures(serialized, start_offset)
  signature = serialized[start_offset..-1]

  multi_signature_offset = 0

  if !signature.length
    @signature = nil
  else
    # First Signature
    signature_length = signature[2, 2].to_i(16) + 2
    @signature = serialized[start_offset, signature_length * 2]

    # Multi Signature
    multi_signature_offset += signature_length * 2

    # Second Signature
    @second_signature = serialized[(start_offset + signature_length * 2)..-1]

    if @second_signature.empty?
      @second_signature = nil
    elsif @second_signature[0, 2] == 'ff'
      @second_signature = nil
    else
      # Second Signature
      second_signature_length = @second_signature[2, 2].to_i(16) + 2
      @second_signature = @second_signature[0, second_signature_length * 2]

      # Multi Signature
      multi_signature_offset += second_signature_length * 2
    end

    # All Signatures
    signatures = serialized[(start_offset + multi_signature_offset)..-1]

    return self if signatures.empty?

    return self if signatures[0, 2] != 'ff'

    # Parse Multi Signatures
    signatures = signatures[2..-1]
    @signatures = []

    more_signatures = true

    while more_signatures
      break if signatures.empty?

      multi_signature_length = signatures[2, 2].to_i(16) + 2

      if multi_signature_length > 0
        @signatures.push(signatures[0, multi_signature_length * 2])
      else
        more_signatures = false
      end

      signatures = signatures[(multi_signature_length * 2)..-1]
    end

    self
  end
end
second_sign(second_passphrase) click to toggle source
# File lib/arkecosystem/crypto/transactions/transaction.rb, line 27
def second_sign(second_passphrase)
  second_key = ArkEcosystem::Crypto::Identities::PrivateKey.from_passphrase(second_passphrase)

  @sign_signature = second_key.ecdsa_signature(Digest::SHA256.digest(to_bytes(false))).unpack('H*').first
  self
end
second_verify(second_public_key) click to toggle source
# File lib/arkecosystem/crypto/transactions/transaction.rb, line 39
def second_verify(second_public_key)
  public_only_key = BTC::Key.new(public_key: [second_public_key].pack('H*'))
  public_only_key.verify_ecdsa_signature([@sign_signature].pack('H*'), Digest::SHA256.digest(to_bytes(false)))
end
serialize(transaction) click to toggle source
# File lib/arkecosystem/crypto/transactions/transaction.rb, line 159
def serialize(transaction)
  ArkEcosystem::Crypto::Serialiser.new(transaction).serialize
end
sign(passphrase) click to toggle source
# File lib/arkecosystem/crypto/transactions/transaction.rb, line 20
def sign(passphrase)
  private_key = ArkEcosystem::Crypto::Identities::PrivateKey.from_passphrase(passphrase)
  @sender_public_key = private_key.public_key.unpack('H*').first
  @signature = private_key.ecdsa_signature(Digest::SHA256.digest(to_bytes)).unpack('H*').first
  self
end
to_bytes(skip_signature = true, skip_second_signature = true) click to toggle source
# File lib/arkecosystem/crypto/transactions/transaction.rb, line 44
def to_bytes(skip_signature = true, skip_second_signature = true)
  bytes = ''
  bytes << [@type].pack('c')
  bytes << [@timestamp].pack('V')
  bytes << [@sender_public_key].pack('H*')

  bytes << if @recipient_id
  BTC::Base58.data_from_base58check(@recipient_id)
  else
    [].pack('x21')
  end

  if @vendor_field
    bytes << @vendor_field

    if @vendor_field.size < 64
      bytes << [].pack("x#{64 - @vendor_field.size}")
    end
  else
    bytes << [].pack('x64')
  end

  bytes << [@amount].pack('Q<')
  bytes << [@fee].pack('Q<')

  case @type
  when ArkEcosystem::Crypto::Enums::Types::SECOND_SIGNATURE_REGISTRATION
    asset_signature_public_key = @asset[:signature][:public_key]

    bytes << [asset_signature_public_key].pack('H*')
  when ArkEcosystem::Crypto::Enums::Types::DELEGATE_REGISTRATION
    bytes << @asset[:delegate][:username]
  when ArkEcosystem::Crypto::Enums::Types::VOTE
    bytes << @asset[:votes].join('')
  when ArkEcosystem::Crypto::Enums::Types::MULTI_SIGNATURE_REGISTRATION
    ms_asset = @asset[:multisignature]

    bytes << [ms_asset[:min]].pack('C')
    bytes << [ms_asset[:lifetime]].pack('C')
    bytes << ms_asset[:keysgroup].join('')
  end

  if !skip_signature && @signature
    bytes << [@signature].pack('H*')
  end

  if !skip_second_signature && @sign_signature
    bytes << [@sign_signature].pack('H*')
  end

  bytes
end
to_json() click to toggle source
# File lib/arkecosystem/crypto/transactions/transaction.rb, line 184
def to_json
  to_params.to_json
end
to_params() click to toggle source
# File lib/arkecosystem/crypto/transactions/transaction.rb, line 167
def to_params
  {
    type: type,
    amount: amount,
    fee: fee,
    vendorField: vendor_field,
    timestamp: timestamp,
    recipientId: recipient_id,
    senderPublicKey: sender_public_key,
    signature: signature,
    id: id
  }.tap do |h|
    h[:asset] = asset.deep_transform_keys { |key| snake_case_to_camel_case(key) } if asset.any?
    h[:signSignature] = sign_signature if sign_signature
  end
end
verify() click to toggle source
# File lib/arkecosystem/crypto/transactions/transaction.rb, line 34
def verify
  public_only_key = BTC::Key.new(public_key: [@sender_public_key].pack('H*'))
  public_only_key.verify_ecdsa_signature([@signature].pack('H*'), Digest::SHA256.digest(to_bytes))
end

Private Instance Methods

snake_case_to_camel_case(string) click to toggle source
# File lib/arkecosystem/crypto/transactions/transaction.rb, line 190
def snake_case_to_camel_case(string)
  string.to_s.split('_').enum_for(:each_with_index).collect do |s, index|
    index.zero? ? s : s.capitalize
  end.join
end