| 470 | |
| 471 | # This is used, eg, for blockchain heights in coinbase scripts (bip34) |
| 472 | class CScriptNum: |
| 473 | __slots__ = ("value",) |
| 474 | |
| 475 | def __init__(self, d=0): |
| 476 | self.value = d |
| 477 | |
| 478 | @staticmethod |
| 479 | def encode(obj): |
| 480 | val = obj.value |
| 481 | r = bytearray(0) |
| 482 | if val == 0: |
| 483 | return bytes(r) |
| 484 | neg = val < 0 |
| 485 | absvalue = -val if neg else val |
| 486 | while (absvalue): |
| 487 | r.append(absvalue & 0xff) |
| 488 | absvalue >>= 8 |
| 489 | if r[-1] & 0x80: |
| 490 | r.append(0x80 if neg else 0) |
| 491 | elif neg: |
| 492 | r[-1] |= 0x80 |
| 493 | return bytes([len(r)]) + r |
| 494 | |
| 495 | @staticmethod |
| 496 | def decode(vch): |
| 497 | result = 0 |
| 498 | # We assume valid push_size and minimal encoding |
| 499 | value = vch[1:] |
| 500 | if len(value) == 0: |
| 501 | return result |
| 502 | for i, byte in enumerate(value): |
| 503 | result |= int(byte) << 8 * i |
| 504 | if value[-1] >= 0x80: |
| 505 | # Mask for all but the highest result bit |
| 506 | num_mask = (2**(len(value) * 8) - 1) >> 1 |
| 507 | result &= num_mask |
| 508 | result *= -1 |
| 509 | return result |
| 510 | |
| 511 | class CScript(bytes): |
| 512 | """Serialized script |
no outgoing calls