Class: ActiveHashcash::Stamp

Inherits:
ApplicationRecord show all
Defined in:
app/models/active_hashcash/stamp.rb

Overview

This is the model to store hashcash stamps. Unless you need something really specific, you should not need interact directly with that class.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.filter_by(params) ⇒ Object



18
19
20
21
22
23
24
25
26
27
# File 'app/models/active_hashcash/stamp.rb', line 18

def self.filter_by(params)
  scope = all
  scope = scope.request_path_starts_with(params[:request_path_starts_with]) if params[:request_path_starts_with].present?
  scope = scope.ip_address_starts_with(params[:ip_address_starts_with]) if params[:ip_address_starts_with].present?
  scope = scope.created_from(params[:created_from]) if params[:created_from].present?
  scope = scope.created_to(params[:created_to]) if params[:created_to].present?
  scope = scope.bits_from(params[:bits_from]) if params[:bits_from].present?
  scope = scope.bits_to(params[:bits_to]) if params[:bits_to].present?
  scope
end

.mint(resource, attributes = {}) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
# File 'app/models/active_hashcash/stamp.rb', line 48

def self.mint(resource, attributes = {})
  new({
    version: 1,
    bits: ActiveHashcash.bits,
    date: Date.today.strftime(ActiveHashcash.date_format),
    resource: resource,
    ext: "sha256",
    rand: SecureRandom.alphanumeric(16),
    counter: 0,
  }.merge(attributes)).work
end

.parse(string) ⇒ Object

Parse and instantiate a stamp from a string which respects the hashcash format:

ver:bits:date:resource:[ext]:rand:counter


42
43
44
45
46
# File 'app/models/active_hashcash/stamp.rb', line 42

def self.parse(string)
  args = string.to_s.split(":")
  return if args.size != 7
  new(version: args[0], bits: args[1], date: Date.strptime(args[2], ActiveHashcash.date_format), resource: args[3], ext: args[4], rand: args[5], counter: args[6])
end

.spend(string, resource, bits, date, options = {}) ⇒ Object

Verify and save the hashcash stamp. Saving in the database prevent from double spending the same stamp.



31
32
33
34
35
36
37
# File 'app/models/active_hashcash/stamp.rb', line 31

def self.spend(string, resource, bits, date, options = {})
  return false unless stamp = parse(string)
  stamp.attributes = options
  stamp.verify(resource, bits, date) && stamp.save
rescue ActiveRecord::RecordNotUnique
  false
end

Instance Method Details

#authentic?Boolean

Returns:

  • (Boolean)


65
66
67
68
69
70
71
# File 'app/models/active_hashcash/stamp.rb', line 65

def authentic?
  if ext == "sha256"
    Digest::SHA256.hexdigest(to_s).hex >> (256 - bits) == 0
  else
    Digest::SHA1.hexdigest(to_s).hex >> (160 - bits) == 0
  end
end

#to_sObject



77
78
79
# File 'app/models/active_hashcash/stamp.rb', line 77

def to_s
  [version.to_i, bits, date.strftime("%y%m%d"), resource, ext, rand, counter].join(":")
end

#verify(resource, bits, date) ⇒ Object



73
74
75
# File 'app/models/active_hashcash/stamp.rb', line 73

def verify(resource, bits, date)
  self.resource == resource && self.bits >= bits && self.date >= date && !self.date.future? && authentic?
end

#workObject



60
61
62
63
# File 'app/models/active_hashcash/stamp.rb', line 60

def work
  counter.next! until authentic?
  self
end