Class: Drand::Chain
- Inherits:
-
Object
- Object
- Drand::Chain
- Defined in:
- lib/drand/chain.rb
Constant Summary collapse
- DEFAULT_ENDPOINTS =
["https://api.drand.sh"].freeze
Instance Attribute Summary collapse
-
#chain_hash ⇒ Object
readonly
Returns the value of attribute chain_hash.
-
#endpoints ⇒ Object
readonly
Returns the value of attribute endpoints.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#period ⇒ Object
readonly
Returns the value of attribute period.
-
#public_key ⇒ Object
readonly
Returns the value of attribute public_key.
-
#scheme ⇒ Object
readonly
Returns the value of attribute scheme.
Instance Method Summary collapse
-
#base_url ⇒ Object
Kept for backward compatibility; returns the first endpoint.
- #current_round ⇒ Object
- #draw(range, round: current_round, verify: verifiable?) ) ⇒ Object
- #genesis_time ⇒ Object
-
#initialize(chain_hash:, genesis_time:, period:, base_url: nil, endpoints: nil, name: "custom", scheme: nil, public_key: nil) ⇒ Chain
constructor
A new instance of Chain.
- #round(number, verify: verifiable?) ) ⇒ Object
- #round_at(time) ⇒ Object
- #time_of(round) ⇒ Object
- #verifiable? ⇒ Boolean
- #verify(round_data) ⇒ Object
Constructor Details
#initialize(chain_hash:, genesis_time:, period:, base_url: nil, endpoints: nil, name: "custom", scheme: nil, public_key: nil) ⇒ Chain
Returns a new instance of Chain.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/drand/chain.rb', line 17 def initialize(chain_hash:, genesis_time:, period:, base_url: nil, endpoints: nil, name: "custom", scheme: nil, public_key: nil) 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 @scheme = scheme @public_key = public_key @endpoints = resolve_endpoints(base_url, endpoints) @http = HttpClient.new(endpoints: @endpoints, chain_hash: chain_hash) end |
Instance Attribute Details
#chain_hash ⇒ Object (readonly)
Returns the value of attribute chain_hash.
15 16 17 |
# File 'lib/drand/chain.rb', line 15 def chain_hash @chain_hash end |
#endpoints ⇒ Object (readonly)
Returns the value of attribute endpoints.
15 16 17 |
# File 'lib/drand/chain.rb', line 15 def endpoints @endpoints end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
15 16 17 |
# File 'lib/drand/chain.rb', line 15 def name @name end |
#period ⇒ Object (readonly)
Returns the value of attribute period.
15 16 17 |
# File 'lib/drand/chain.rb', line 15 def period @period end |
#public_key ⇒ Object (readonly)
Returns the value of attribute public_key.
15 16 17 |
# File 'lib/drand/chain.rb', line 15 def public_key @public_key end |
#scheme ⇒ Object (readonly)
Returns the value of attribute scheme.
15 16 17 |
# File 'lib/drand/chain.rb', line 15 def scheme @scheme end |
Instance Method Details
#base_url ⇒ Object
Kept for backward compatibility; returns the first endpoint.
38 39 40 |
# File 'lib/drand/chain.rb', line 38 def base_url @endpoints.first end |
#current_round ⇒ Object
59 60 61 |
# File 'lib/drand/chain.rb', line 59 def current_round round_at(Time.now.utc) end |
#draw(range, round: current_round, verify: verifiable?) ) ⇒ Object
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/drand/chain.rb', line 73 def draw(range, round: current_round, verify: verifiable?) lo, hi = normalize_range(range) data = self.round(round, verify: verify) { 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: data[:verified], served_by: data[:served_by] } end |
#genesis_time ⇒ Object
42 43 44 |
# File 'lib/drand/chain.rb', line 42 def genesis_time Time.at(@genesis_unix).utc end |
#round(number, verify: verifiable?) ) ⇒ Object
63 64 65 66 67 68 69 70 71 |
# File 'lib/drand/chain.rb', line 63 def round(number, verify: verifiable?) 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 data = @http.fetch_round(number) data[:verified] = verify ? verify!(data) : false data end |
#round_at(time) ⇒ Object
46 47 48 49 50 51 |
# File 'lib/drand/chain.rb', line 46 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
53 54 55 56 57 |
# File 'lib/drand/chain.rb', line 53 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 |
#verifiable? ⇒ Boolean
33 34 35 |
# File 'lib/drand/chain.rb', line 33 def verifiable? !@scheme.nil? && !@public_key.nil? end |
#verify(round_data) ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/drand/chain.rb', line 89 def verify(round_data) unless verifiable? raise VerificationError, "chain has no public_key/scheme; cannot verify" end Verifier.verify( scheme: @scheme, public_key: @public_key, round: round_data.fetch(:round), signature: round_data.fetch(:signature), previous_signature: round_data[:previous_signature] ) end |