Class: Chain::HSMSigner
- Inherits:
-
Object
- Object
- Chain::HSMSigner
- Defined in:
- lib/chain/hsm_signer.rb
Instance Method Summary collapse
-
#add_key(xpub_or_key, signer_conn) ⇒ Object
Add a new key/signer pair to the HSM signer.
-
#initialize ⇒ HSMSigner
constructor
A new instance of HSMSigner.
-
#sign(tx_template) ⇒ Object
Sign a single transaction.
-
#sign_batch(tx_templates) ⇒ Object
Sign a batch of transactions.
Constructor Details
#initialize ⇒ HSMSigner
Returns a new instance of HSMSigner.
9 10 11 |
# File 'lib/chain/hsm_signer.rb', line 9 def initialize @xpubs_by_signer = {} end |
Instance Method Details
#add_key(xpub_or_key, signer_conn) ⇒ Object
Add a new key/signer pair to the HSM signer.
16 17 18 19 20 21 |
# File 'lib/chain/hsm_signer.rb', line 16 def add_key(xpub_or_key, signer_conn) xpub = xpub_or_key.is_a?(MockHSM::Key) ? xpub_or_key.xpub : xpub_or_key @xpubs_by_signer[signer_conn] ||= [] @xpubs_by_signer[signer_conn] << xpub @xpubs_by_signer[signer_conn].uniq! end |
#sign(tx_template) ⇒ Object
Sign a single transaction
25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/chain/hsm_signer.rb', line 25 def sign(tx_template) return tx_template if @xpubs_by_signer.empty? @xpubs_by_signer.each do |signer_conn, xpubs| tx_template = signer_conn.singleton_batch_request( '/sign-transaction', transactions: [tx_template], xpubs: xpubs, ) { |item| Transaction::Template.new(item) } end tx_template end |
#sign_batch(tx_templates) ⇒ Object
Sign a batch of transactions
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/chain/hsm_signer.rb', line 41 def sign_batch(tx_templates) if @xpubs_by_signer.empty? # Treat all templates as if signed successfully. successes = tx_templates.each_with_index.reduce({}) do |memo, (t, i)| memo[i] = t memo end BatchResponse.new(successes: successes) end # We need to work towards a single, final BatchResponse that uses the # original indexes. For the next cycle, we should retain only those # templates for which the most recent sign response was successful, and # maintain a mapping of each template's index in the upcoming request # to its original index. orig_index = (0...tx_templates.size).to_a errors = {} @xpubs_by_signer.each do |signer_conn, xpubs| next_tx_templates = [] next_orig_index = [] batch = signer_conn.batch_request( '/sign-transaction', transactions: tx_templates, xpubs: xpubs, ) { |item| Transaction::Template.new(item) } batch.successes.each do |i, template| next_tx_templates << template next_orig_index << orig_index[i] end batch.errors.each do |i, err| errors[orig_index[i]] = err end tx_templates = next_tx_templates orig_index = next_orig_index # Early-exit if all templates have encountered an error. break if tx_templates.empty? end successes = tx_templates.each_with_index.reduce({}) do |memo, (t, i)| memo[orig_index[i]] = t memo end BatchResponse.new( successes: successes, errors: errors, ) end |