Class: BTC::ScriptNumber
- Inherits:
-
Object
- Object
- BTC::ScriptNumber
- Defined in:
- lib/btcruby/script/script_number.rb
Constant Summary collapse
- DEFAULT_MAX_SIZE =
4- INT64_MAX =
0x7fffffffffffffff- INT64_MIN =
- 1
Class Method Summary collapse
Instance Method Summary collapse
- #!=(other) ⇒ Object
- #*(other) ⇒ Object
- #+(other) ⇒ Object
- #+@ ⇒ Object
- #-(other) ⇒ Object
- #-@ ⇒ Object
- #/(other) ⇒ Object
- #<(other) ⇒ Object
- #<<(other) ⇒ Object
- #<=(other) ⇒ Object
-
#==(other) ⇒ Object
Operators.
- #>(other) ⇒ Object
- #>=(other) ⇒ Object
- #>>(other) ⇒ Object
- #assert(condition, message) ⇒ Object
- #data ⇒ Object
-
#initialize(integer: nil, boolean: nil, data: nil, hex: nil, require_minimal: true, max_size: DEFAULT_MAX_SIZE) ⇒ ScriptNumber
constructor
A new instance of ScriptNumber.
- #to_hex ⇒ Object
-
#to_i ⇒ Object
Conversion Methods.
- #to_s ⇒ Object
Constructor Details
#initialize(integer: nil, boolean: nil, data: nil, hex: nil, require_minimal: true, max_size: DEFAULT_MAX_SIZE) ⇒ ScriptNumber
Returns a new instance of ScriptNumber.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/btcruby/script/script_number.rb', line 17 def initialize(integer: nil, boolean: nil, data: nil, hex: nil, require_minimal: true, max_size: DEFAULT_MAX_SIZE) if integer assert(integer >= INT64_MIN && integer <= INT64_MAX, "Integer must be within int64 range") @integer = integer elsif boolean == false || boolean == true @integer = boolean ? 1 : 0 elsif data || hex data ||= BTC.from_hex(hex) if data.bytesize > max_size raise ScriptNumberError, "script number overflow (#{data.bytesize} > #{max_size})" end if require_minimal && data.bytesize > 0 # Check that the number is encoded with the minimum possible # number of bytes. # # If the most-significant-byte - excluding the sign bit - is zero # then we're not minimal. Note how this test also rejects the # negative-zero encoding, 0x80. if (data.bytes.last & 0x7f) == 0 # One exception: if there's more than one byte and the most # significant bit of the second-most-significant-byte is set # it would conflict with the sign bit. An example of this case # is +-255, which encode to 0xff00 and 0xff80 respectively. # (big-endian). if data.bytesize <= 1 || (data.bytes[data.bytesize - 2] & 0x80) == 0 raise ScriptNumberError, "non-minimally encoded script number" end end end @integer = self.class.decode_integer(data) else raise ArgumentError end end |
Class Method Details
.decode_integer(data) ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/btcruby/script/script_number.rb', line 124 def self.decode_integer(data) return 0 if data.empty? result = 0 bytes = data.bytes bytes.each_with_index do |byte, i| result |= bytes[i] << 8*i end # If the input vector's most significant byte is 0x80, remove it from # the result's msb and return a negative. if (bytes.last & 0x80) != 0 return -(result & ~(0x80 << (8 * (bytes.size - 1)))); end return result end |
.encode_integer(value) ⇒ Object
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/btcruby/script/script_number.rb', line 142 def self.encode_integer(value) return "".b if value == 0 result = [] negative = value < 0 absvalue = negative ? -value : value while absvalue != 0 result.push(absvalue & 0xff) absvalue >>= 8 end # - If the most significant byte is >= 0x80 and the value is positive, push a # new zero-byte to make the significant byte < 0x80 again. # # - If the most significant byte is >= 0x80 and the value is negative, push a # new 0x80 byte that will be popped off when converting to an integral. # # - If the most significant byte is < 0x80 and the value is negative, add # 0x80 to it, since it will be subtracted and interpreted as a negative when # converting to an integral. if (result.last & 0x80) != 0 result.push(negative ? 0x80 : 0) elsif negative result[result.size - 1] = result.last | 0x80 end BTC.data_from_bytes(result) end |
Instance Method Details
#!=(other) ⇒ Object
55 |
# File 'lib/btcruby/script/script_number.rb', line 55 def !=(other); @integer != other.to_i; end |
#*(other) ⇒ Object
73 74 75 76 |
# File 'lib/btcruby/script/script_number.rb', line 73 def *(other) # TODO: add asserts to check that result fits within int64 limits self.class.new(integer: @integer * other.to_i) end |
#+(other) ⇒ Object
61 |
# File 'lib/btcruby/script/script_number.rb', line 61 def +(other); self.class.new(integer: @integer + other.to_i); end |
#+@ ⇒ Object
64 65 66 |
# File 'lib/btcruby/script/script_number.rb', line 64 def +@ self end |
#-(other) ⇒ Object
62 |
# File 'lib/btcruby/script/script_number.rb', line 62 def -(other); self.class.new(integer: @integer - other.to_i); end |
#-@ ⇒ Object
68 69 70 71 |
# File 'lib/btcruby/script/script_number.rb', line 68 def -@ assert(@integer > INT64_MIN && @integer <= INT64_MAX, "Integer will not be within int64 range after negation") self.class.new(integer: -@integer) end |
#/(other) ⇒ Object
78 79 80 81 |
# File 'lib/btcruby/script/script_number.rb', line 78 def /(other) # TODO: add asserts to check that result fits within int64 limits self.class.new(integer: @integer / other.to_i) end |
#<(other) ⇒ Object
57 |
# File 'lib/btcruby/script/script_number.rb', line 57 def <(other); @integer < other.to_i; end |
#<<(other) ⇒ Object
83 84 85 86 87 88 89 90 91 92 |
# File 'lib/btcruby/script/script_number.rb', line 83 def <<(other) # TODO: add asserts to check that result fits within int64 limits assert(other >= 0, "Shift amount must not be negative") a = @integer.abs r = a << other.to_i if a != @integer r = -r end self.class.new(integer: r) end |
#<=(other) ⇒ Object
56 |
# File 'lib/btcruby/script/script_number.rb', line 56 def <=(other); @integer <= other.to_i; end |
#==(other) ⇒ Object
Operators
54 |
# File 'lib/btcruby/script/script_number.rb', line 54 def ==(other); @integer == other.to_i; end |
#>(other) ⇒ Object
59 |
# File 'lib/btcruby/script/script_number.rb', line 59 def >(other); @integer > other.to_i; end |
#>=(other) ⇒ Object
58 |
# File 'lib/btcruby/script/script_number.rb', line 58 def >=(other); @integer >= other.to_i; end |
#>>(other) ⇒ Object
94 95 96 97 98 99 100 101 102 103 |
# File 'lib/btcruby/script/script_number.rb', line 94 def >>(other) # TODO: add asserts to check that result fits within int64 limits assert(other >= 0, "Shift amount must not be negative") a = @integer.abs r = a >> other.to_i if a != @integer r = -r end self.class.new(integer: r) end |
#assert(condition, message) ⇒ Object
173 174 175 |
# File 'lib/btcruby/script/script_number.rb', line 173 def assert(condition, ) raise if !condition end |
#data ⇒ Object
116 117 118 |
# File 'lib/btcruby/script/script_number.rb', line 116 def data self.class.encode_integer(@integer) end |
#to_hex ⇒ Object
120 121 122 |
# File 'lib/btcruby/script/script_number.rb', line 120 def to_hex BTC.to_hex(data) end |
#to_i ⇒ Object
Conversion Methods
108 109 110 |
# File 'lib/btcruby/script/script_number.rb', line 108 def to_i @integer end |
#to_s ⇒ Object
112 113 114 |
# File 'lib/btcruby/script/script_number.rb', line 112 def to_s @integer.to_s end |