Class: Ciri::Chain::Transaction

Inherits:
Object
  • Object
show all
Includes:
RLP::Serializable, Types
Defined in:
lib/ciri/chain/transaction.rb

Direct Known Subclasses

Forks::Frontier::Transaction

Defined Under Namespace

Classes: InvalidError

Constant Summary collapse

EIP155_CHAIN_ID_OFFSET =
35
V_OFFSET =
27

Constants included from RLP::Serializable

RLP::Serializable::TYPES

Instance Attribute Summary

Attributes included from RLP::Serializable

#serializable_attributes

Instance Method Summary collapse

Methods included from RLP::Serializable

#==, included, #initialize, #initialize_copy, #rlp_encode

Instance Method Details

#chain_idObject

return chain_id by v



117
118
119
120
121
122
# File 'lib/ciri/chain/transaction.rb', line 117

def chain_id
  if eip_155_signed_transaction?
    # retrieve chain_id from v, see EIP-155
    (v - 35) / 2
  end
end

#contract_creation?Boolean

Returns:

  • (Boolean)


84
85
86
# File 'lib/ciri/chain/transaction.rb', line 84

def contract_creation?
  to.empty?
end

#eip_155_signed_transaction?Boolean

Returns:

  • (Boolean)


125
126
127
# File 'lib/ciri/chain/transaction.rb', line 125

def eip_155_signed_transaction?
  v >= EIP155_CHAIN_ID_OFFSET
end

#get_hashObject



97
98
99
# File 'lib/ciri/chain/transaction.rb', line 97

def get_hash
  Utils.keccak rlp_encode
end

#senderObject

sender address

Returns:

  • address String



55
56
57
58
59
60
61
# File 'lib/ciri/chain/transaction.rb', line 55

def sender
  @sender ||= begin
    address = Key.ecdsa_recover(sign_hash(chain_id), signature).to_address
    address.validate
    address
  end
end

#sign_hash(chain_id = nil) ⇒ Object



88
89
90
91
92
93
94
95
# File 'lib/ciri/chain/transaction.rb', line 88

def sign_hash(chain_id = nil)
  param = data || ''.b
  list = [nonce, gas_price, gas_limit, to, value, param]
  if chain_id
    list += [chain_id, ''.b, ''.b]
  end
  Utils.keccak(RLP.encode_simple list)
end

#sign_with_key!(key) ⇒ Object

Parameters:

  • key

    Key



76
77
78
79
80
81
82
# File 'lib/ciri/chain/transaction.rb', line 76

def sign_with_key!(key)
  signature = key.ecdsa_signature(sign_hash)
  self.v = signature.v
  self.r = signature.r
  self.s = signature.s
  nil
end

#signatureObject



63
64
65
66
67
68
69
70
71
72
73
# File 'lib/ciri/chain/transaction.rb', line 63

def signature
  v = if eip_155_signed_transaction?
        # retrieve actually v from transaction.v, see EIP-155(prevent replay attack)
        (self.v - 1) % 2
      elsif [27, 28].include?(self.v)
        self.v - 27
      else
        self.v
      end
  Crypto::Signature.new(vrs: [v, r, s])
end

#validate!Object

validate transaction

Raises:

  • (NotImplementedError)


102
103
104
# File 'lib/ciri/chain/transaction.rb', line 102

def validate!
  raise NotImplementedError
end

#validate_sender!Object



106
107
108
109
110
111
112
113
114
# File 'lib/ciri/chain/transaction.rb', line 106

def validate_sender!
  begin
    sender
  rescue Ciri::Crypto::ECDSASignatureError => e
    raise InvalidError.new("recover signature error, error: #{e}")
  rescue Ciri::Types::Errors::InvalidError => e
    raise InvalidError.new(e.to_s)
  end
end