Class: Drand::Chain

Inherits:
Object
  • Object
show all
Defined in:
lib/drand/chain.rb

Constant Summary collapse

DEFAULT_ENDPOINTS =
["https://api.drand.sh"].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(chain_hash:, genesis_time:, period:, base_url: nil, endpoints: nil, name: "custom") ⇒ Chain

Returns a new instance of Chain.

Raises:



16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/drand/chain.rb', line 16

def initialize(chain_hash:, genesis_time:, period:, base_url: nil, endpoints: nil, name: "custom")
  raise ArgumentError, "chain_hash required" if chain_hash.nil? || chain_hash.empty?
  raise ArgumentError, "genesis_time must be an Integer" unless genesis_time.is_a?(Integer)
  raise ArgumentError, "period must be a positive Integer" unless period.is_a?(Integer) && period.positive?

  @chain_hash = chain_hash
  @genesis_unix = genesis_time
  @period = period
  @name = name
  @endpoints = resolve_endpoints(base_url, endpoints)
  @http = HttpClient.new(endpoints: @endpoints, chain_hash: chain_hash)
end

Instance Attribute Details

#chain_hashObject (readonly)

Returns the value of attribute chain_hash.



14
15
16
# File 'lib/drand/chain.rb', line 14

def chain_hash
  @chain_hash
end

#endpointsObject (readonly)

Returns the value of attribute endpoints.



14
15
16
# File 'lib/drand/chain.rb', line 14

def endpoints
  @endpoints
end

#nameObject (readonly)

Returns the value of attribute name.



14
15
16
# File 'lib/drand/chain.rb', line 14

def name
  @name
end

#periodObject (readonly)

Returns the value of attribute period.



14
15
16
# File 'lib/drand/chain.rb', line 14

def period
  @period
end

Instance Method Details

#base_urlObject

Kept for backward compatibility; returns the first endpoint.



30
31
32
# File 'lib/drand/chain.rb', line 30

def base_url
  @endpoints.first
end

#current_roundObject



51
52
53
# File 'lib/drand/chain.rb', line 51

def current_round
  round_at(Time.now.utc)
end

#draw(range, round: current_round) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/drand/chain.rb', line 63

def draw(range, round: current_round)
  lo, hi = normalize_range(range)
  data = self.round(round)
  {
    value: sample_in(data[:randomness], lo, hi),
    range: { min: lo, max: hi },
    round: data[:round],
    chain: @name,
    chain_hash: @chain_hash,
    randomness: data[:randomness],
    signature: data[:signature],
    verified: false,
    served_by: data[:served_by]
  }
end

#genesis_timeObject



34
35
36
# File 'lib/drand/chain.rb', line 34

def genesis_time
  Time.at(@genesis_unix).utc
end

#round(number) ⇒ Object

Raises:



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

def round(number)
  raise ArgumentError, "round must be an Integer" unless number.is_a?(Integer)
  raise RoundError, "round must be >= 1" if number < 1
  raise RoundError, "round #{number} is in the future" if number > current_round

  @http.fetch_round(number).merge(verified: false)
end

#round_at(time) ⇒ Object

Raises:



38
39
40
41
42
43
# File 'lib/drand/chain.rb', line 38

def round_at(time)
  t = to_utc(time)
  elapsed = t.to_r - @genesis_unix
  raise RoundError, "time is before chain genesis" if elapsed.negative?
  (elapsed / @period).floor + 1
end

#time_of(round) ⇒ Object

Raises:



45
46
47
48
49
# File 'lib/drand/chain.rb', line 45

def time_of(round)
  raise ArgumentError, "round must be an Integer" unless round.is_a?(Integer)
  raise RoundError, "round must be >= 1" if round < 1
  Time.at(@genesis_unix + (round - 1) * @period).utc
end