@btc-vision/btc-runtime
Version:
Bitcoin Smart Contract Runtime
55 lines (47 loc) • 1.73 kB
text/typescript
import { Blockchain } from '../env';
import { Potential } from '../lang/Definitions';
import { bigEndianAdd } from '../math/bytes';
import { Plugin } from '../plugins/Plugin';
/**
* A unique key in storage that holds the next free "offset" as a 256-bit counter.
* You can change this to any 32-byte constant you like.
*/
const ALLOCATOR_KEY = new Uint8Array(32);
for (let i = 0; i < 32; i++) {
ALLOCATOR_KEY[i] = 0xff;
}
/**
* PointerManager: ensures we never collide while allocating variable-length data.
* - We store a global "offset" in ALLOCATOR_KEY (as a big-endian u256).
* - Each time we allocate N slots (N * 32 bytes), we do:
* oldOffset = currentGlobalOffset
* newOffset = oldOffset + N
* store newOffset back
* return oldOffset as the base pointer
*/
class _PointerManager extends Plugin {
private _cachedOffset: Potential<Uint8Array> = null;
private get cachedOffset(): Uint8Array {
if (!this._cachedOffset) {
this._cachedOffset = Blockchain.getStorageAt(ALLOCATOR_KEY);
}
return this._cachedOffset as Uint8Array;
}
/**
* Allocates `numSlots` (each 32 bytes). Returns a 32-byte pointer (u256 in big-endian).
*
* Each slot is conceptually:
* slot0 = pointer + 0
* slot1 = pointer + 1
* ...
* and so forth in big-endian arithmetic.
*/
public allocateSlots(numSlots: u64): Uint8Array {
this._cachedOffset = bigEndianAdd(this.cachedOffset, numSlots);
const val = this.cachedOffset;
Blockchain.setStorageAt(ALLOCATOR_KEY, val);
return val;
}
}
export const PointerManager = new _PointerManager();
Blockchain.registerPlugin(PointerManager);