Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ extension Ref where T == ProtocolConfig {
maxWorkItems: 16,
maxDepsInWorkReport: 8,
maxTicketsPerExtrinsic: 3,
maxLookupAnchorAge: 14400,
maxLookupAnchorAge: 24,
transferMemoSize: 128,
ticketEntriesPerValidator: 3,
maxAuthorizationsPoolItems: 8,
Expand Down
9 changes: 7 additions & 2 deletions Blockchain/Sources/Blockchain/Types/Ticket.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import Codec
import Utils

public struct Ticket: Sendable, Equatable, Codable {
public struct Ticket: @unchecked Sendable, Equatable, Codable {
// y
public var id: Data32
// r
public var attempt: TicketIndex
@CodingAs<Compact<TicketIndex>> public var attempt: TicketIndex

public static func == (lhs: Ticket, rhs: Ticket) -> Bool {
lhs.id == rhs.id && lhs.attempt == rhs.attempt
}
}

extension Ticket: Dummy {
Expand Down
1 change: 1 addition & 0 deletions Codec/Sources/Codec/IntegerCodec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ extension Collection<UInt8> where SubSequence == Self {
IntegerCodec.decode { self.next() }
}

// NOTE: for data, use decodeUInt* methods in Data+Utils.swift for better performance
public mutating func decode<T: UnsignedInteger>(length: Int) -> T? {
guard length > 0, length <= count else { return nil }

Expand Down
Binary file removed JAMTests/fuzz/0.7.0/1756548916/00000081.bin
Binary file not shown.
748 changes: 0 additions & 748 deletions JAMTests/fuzz/0.7.0/1756548916/00000081.json

This file was deleted.

Binary file removed JAMTests/fuzz/0.7.0/1756548916/00000082.bin
Binary file not shown.
746 changes: 0 additions & 746 deletions JAMTests/fuzz/0.7.0/1756548916/00000082.json

This file was deleted.

Binary file removed JAMTests/fuzz/0.7.0/1757063641/00000179.bin
Binary file not shown.
205 changes: 0 additions & 205 deletions JAMTests/fuzz/0.7.0/1757063641/00000179.json

This file was deleted.

Binary file removed JAMTests/fuzz/0.7.0/1757063641/00000180.bin
Binary file not shown.
254 changes: 0 additions & 254 deletions JAMTests/fuzz/0.7.0/1757063641/00000180.json

This file was deleted.

2 changes: 1 addition & 1 deletion Node/Tests/NodeTests/chainfiles/spec-tiny.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@
"10000000000000000000000000000000000000000000000000000000000000" : "0x00"
},
"id" : "tiny",
"protocol_parameters" : "0x0a00000000000000010000000000000064000000000000000200200000000c000000809698000000000080f0fa020000000000ca9a3b00000000002d3101000000000800100008000300403800000300080006005000040080000500060000fa0000017cd20000093d0004000000000c00000204000000c0000080000000000c00000a000000"
"protocol_parameters" : "0x0a00000000000000010000000000000064000000000000000200200000000c000000809698000000000080f0fa020000000000ca9a3b00000000002d3101000000000800100008000300180000000300080006005000040080000500060000fa0000017cd20000093d0004000000000c00000204000000c0000080000000000c00000a000000"
}
7 changes: 5 additions & 2 deletions PolkaVM/Sources/PolkaVM/InstructionTable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,16 @@ public class InstructionTable {
guard data.count >= 1 else {
return nil
}

let opcode = data[data.startIndex]
// logger.trace("parsed opcode: \(opcode)")

guard let instType = table[Int(opcode)] else {
return nil
}

// logger.trace("initializing \(instType)")
return try? instType.init(data: data[relative: 1...])

let instructionData = data.subdata(in: (data.startIndex + 1) ..< data.endIndex)
return try? instType.init(data: instructionData)
}
}
23 changes: 18 additions & 5 deletions PolkaVM/Sources/PolkaVM/Instructions/Instructions+Helpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ extension Instructions {
let lY = min(4, max(0, data.count - Int(lX) - minus))

let start = startIdx + 1
let vX: T = decodeImmediate((try? data.at(relative: start ..< (start + lX))) ?? Data())
let vY: U = decodeImmediate((try? data.at(relative: (start + lX) ..< (start + lX + lY))) ?? Data())
let vX: T = decodeImmediate(data.subdata(in: data.startIndex + start ..< data.startIndex + (start + lX)))
let vY: U = decodeImmediate(data.subdata(in: data.startIndex + (start + lX) ..< data.startIndex + (start + lX + lY)))
return (vX, vY)
}

Expand Down Expand Up @@ -69,14 +69,27 @@ extension Instructions {
return .exit(.panic(.invalidDynamicJump))
}

var targetAlignedData = jumpTable[relative: start ..< end]
var targetAlignedData = jumpTable.subdata(in: jumpTable.startIndex + start ..< jumpTable.startIndex + end)

#if DEBUG
logger.trace("djump target data (\(targetAlignedData.map(\.self)))")
#endif

guard let targetAligned: UInt32 = targetAlignedData.decode(length: entrySize) else {
return .exit(.panic(.invalidDynamicJump))
let targetAligned: UInt32
switch entrySize {
case 1:
targetAligned = UInt32(targetAlignedData.decodeUInt8())
case 2:
targetAligned = UInt32(targetAlignedData.decodeUInt16())
case 3:
targetAligned = targetAlignedData.decodeUInt24()
case 4:
targetAligned = targetAlignedData.decodeUInt32()
default:
guard let decoded: UInt32 = targetAlignedData.decode(length: entrySize) else {
return .exit(.panic(.invalidDynamicJump))
}
targetAligned = decoded
}

#if DEBUG
Expand Down
130 changes: 65 additions & 65 deletions PolkaVM/Sources/PolkaVM/Instructions/Instructions.swift

Large diffs are not rendered by default.

12 changes: 9 additions & 3 deletions PolkaVM/Sources/PolkaVM/Memory/StandardMemory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,12 @@ public final class StandardMemory: Memory {
try ensureReadable(address: address, length: 1)
let zone = try getZone(for: address)
let offset = zone.offset(for: address)
if offset < zone.data.count {
return zone.data[relative: offset]

guard offset < zone.data.count else {
return 0
}
return 0

return zone.data[relative: offset]
}

public func read(address: UInt32, length: Int) throws -> Data {
Expand All @@ -143,6 +145,10 @@ public final class StandardMemory: Memory {
let zone = try getZone(for: address)
let offset = zone.offset(for: address)

if length <= zone.data.count - offset {
return zone.data.subdata(in: zone.data.startIndex + offset ..< (zone.data.startIndex + offset + length))
}

var result = Data(count: length)
let availableBytes = max(0, zone.data.count - offset)
let bytesToCopy = min(length, availableBytes)
Expand Down
12 changes: 7 additions & 5 deletions PolkaVM/Sources/PolkaVM/ProgramCode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public class ProgramCode {

private var blockGasCosts: [UInt32: Gas] = [:]

private static let cachedTrapInst = CppHelper.Instructions.Trap()

public init(_ blob: Data) throws(Error) {
self.blob = blob

Expand Down Expand Up @@ -87,6 +89,8 @@ public class ProgramCode {
bitmask = bitmaskData

try buildMetadata()

instCache = Array(repeating: nil, count: code.count)
}

private func buildMetadata() throws(Error) {
Expand Down Expand Up @@ -136,18 +140,16 @@ public class ProgramCode {
public func getInstructionAt(pc: UInt32) -> Instruction? {
let pcIndex = Int(pc)

if instCache.count <= pcIndex {
instCache.append(contentsOf: Array(repeating: nil, count: pcIndex - instCache.count + 1))
if pcIndex >= instCache.count {
return Self.cachedTrapInst
}

if let cached = instCache[pcIndex] {
return cached.instruction
}

guard Int(pc) < code.count else {
let trapInst = CppHelper.Instructions.Trap()
instCache[pcIndex] = InstRef(trapInst)
return trapInst
return Self.cachedTrapInst
}

do {
Expand Down
14 changes: 9 additions & 5 deletions PolkaVM/Sources/PolkaVM/VMStateInterpreter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import Utils
public class VMStateInterpreter: VMState {
public let program: ProgramCode

public private(set) var pc: UInt32
private var _pc: UInt32

public var pc: UInt32 {
_pc
}

private var registers: Registers
private var gas: GasInt
Expand All @@ -14,7 +18,7 @@ public class VMStateInterpreter: VMState {

public init(program: ProgramCode, pc: UInt32, registers: Registers, gas: Gas, memory: Memory) {
self.program = program
self.pc = pc
_pc = pc
self.registers = registers
self.gas = GasInt(gas)
self.memory = memory
Expand All @@ -26,7 +30,7 @@ public class VMStateInterpreter: VMState {
self.program = program.code
registers = program.initialRegisters
memory = program.initialMemory
self.pc = pc
_pc = pc
self.gas = GasInt(gas)
}

Expand Down Expand Up @@ -111,11 +115,11 @@ public class VMStateInterpreter: VMState {
public func increasePC(_ amount: UInt32) {
// using wrapped add
// so that it can also be used for jumps which are negative
pc &+= amount
_pc &+= amount
}

public func updatePC(_ newPC: UInt32) {
pc = newPC
_pc = newPC
}

public func readRegister<T: FixedWidthInteger>(_ index: Registers.Index) -> T {
Expand Down
31 changes: 31 additions & 0 deletions Utils/Sources/Utils/Extensions/Data+Utils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,37 @@ extension Data {
ptr.loadUnaligned(as: T.self)
}
}

public func decodeUInt8() -> UInt8 {
assert(count >= 1)
return self[0]
}

public func decodeUInt16() -> UInt16 {
assert(count >= 2)
return withUnsafeBytes { ptr in
ptr.loadUnaligned(as: UInt16.self)
}
}

public func decodeUInt24() -> UInt32 {
assert(count >= 3)
return UInt32(self[0]) | (UInt32(self[1]) << 8) | (UInt32(self[2]) << 16)
}

public func decodeUInt32() -> UInt32 {
assert(count >= 4)
return withUnsafeBytes { ptr in
ptr.loadUnaligned(as: UInt32.self)
}
}

public func decodeUInt64() -> UInt64 {
assert(count >= 8)
return withUnsafeBytes { ptr in
ptr.loadUnaligned(as: UInt64.self)
}
}
}

extension FixedSizeData {
Expand Down
12 changes: 10 additions & 2 deletions Utils/Sources/bandersnatch/src/bandersnatch_vrfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,16 @@ pub struct RingVrfSignature {
}

pub fn ring_context(size: usize) -> Option<RingProofParams> {
let pcs_params = ring_context_params();
RingProofParams::from_pcs_params(size, pcs_params.clone()).ok()
use std::sync::OnceLock;
static RING_CONTEXT: OnceLock<Option<RingProofParams>> = OnceLock::new();

// size is number of validators, so it won't change
RING_CONTEXT
.get_or_init(|| {
let pcs_params = ring_context_params();
RingProofParams::from_pcs_params(size, pcs_params.clone()).ok()
})
.clone()
}

fn ring_context_params() -> &'static PcsParams {
Expand Down
Loading