Skip to content

Commit

Permalink
Merge branch 'master' into dev_rpc
Browse files Browse the repository at this point in the history
* master:
  fix typo (#267)
  0.5.4 updates (#266)
  • Loading branch information
MacOMNI committed Jan 21, 2025
2 parents bd304e2 + 65a0f46 commit 72f1411
Show file tree
Hide file tree
Showing 11 changed files with 692 additions and 154 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public struct DeferredTransfers: Codable {
/// which are both needed and mutable by the accumulation process.
public struct AccumulateState {
/// d
public var serviceAccounts: [ServiceIndex: ServiceAccount]
public var newServiceAccounts: [ServiceIndex: ServiceAccount]
/// i
public var validatorQueue: ConfigFixedSizeArray<
ValidatorKey, ProtocolConfig.TotalNumberOfValidators
Expand All @@ -63,7 +63,7 @@ public struct AccumulateState {

/// X
public struct AccumlateResultContext {
/// d
/// d: all existing service accounts
public var serviceAccounts: ServiceAccounts
/// s: the accumulating service account index
public var serviceIndex: ServiceIndex
Expand All @@ -73,6 +73,8 @@ public struct AccumlateResultContext {
public var nextAccountIndex: ServiceIndex
/// t: deferred transfers
public var transfers: [DeferredTransfers]
/// y
public var yield: Data32?
}

public protocol AccumulateFunction {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ extension Accumulation {
}

// new service accounts
for (service, account) in singleOutput.state.serviceAccounts {
for (service, account) in singleOutput.state.newServiceAccounts {
guard newServiceAccounts[service] == nil, try await get(serviceAccount: service) == nil else {
throw AccumulationError.duplicatedServiceIndex
}
Expand All @@ -201,7 +201,7 @@ extension Accumulation {
return ParallelAccumulationOutput(
gasUsed: gasUsed,
state: AccumulateState(
serviceAccounts: newServiceAccounts,
newServiceAccounts: newServiceAccounts,
validatorQueue: newValidatorQueue ?? validatorQueue,
authorizationQueue: newAuthorizationQueue ?? authorizationQueue,
privilegedServices: newPrivilegedServices ?? privilegedServices
Expand Down Expand Up @@ -339,7 +339,7 @@ extension Accumulation {
config: config,
block: block,
state: AccumulateState(
serviceAccounts: [:],
newServiceAccounts: [:],
validatorQueue: validatorQueue,
authorizationQueue: authorizationQueue,
privilegedServices: privilegedServices
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ public final class Runtime {
state.authorizationQueue = accumulateState.authorizationQueue
state.validatorQueue = accumulateState.validatorQueue
state.privilegedServices = accumulateState.privilegedServices
for (service, account) in accumulateState.serviceAccounts {
for (service, account) in accumulateState.newServiceAccounts {
state[serviceAccount: service] = account.toDetails()
for (hash, value) in account.storage {
state[serviceAccount: service, storageKey: hash] = value
Expand Down
4 changes: 2 additions & 2 deletions Blockchain/Sources/Blockchain/Types/ServiceAccount.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public struct ServiceAccountDetails: Sendable, Equatable, Codable {
// m
public var minOnTransferGas: Gas

// l: the total number of octets used in storage
// o: the total number of octets used in storage
public var totalByteLength: UInt64

// i: number of items in storage
Expand Down Expand Up @@ -104,7 +104,7 @@ extension ServiceAccount {
UInt32(2 * preimageInfos.count + storage.count)
}

// l: the total number of octets used in storage
// o: the total number of octets used in storage
public var totalByteLength: UInt64 {
let preimageInfosBytes = preimageInfos.keys.reduce(into: 0) { $0 += 81 + $1.length }
let storageBytes = storage.values.reduce(into: 0) { $0 += 32 + $1.count }
Expand Down
178 changes: 123 additions & 55 deletions Blockchain/Sources/Blockchain/VMInvocations/HostCall/HostCalls.swift
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,11 @@ public class New: HostCall {
x.serviceAccounts.set(serviceAccount: x.serviceIndex, account: acc)

state.writeRegister(Registers.Index(raw: 7), x.nextAccountIndex)
x.accumulateState.serviceAccounts.merge([x.nextAccountIndex: newAccount]) { _, new in new }
x.nextAccountIndex = AccumulateContext.check(i: bump(i: x.nextAccountIndex), serviceAccounts: x.accumulateState.serviceAccounts)
x.accumulateState.newServiceAccounts.merge([x.nextAccountIndex: newAccount]) { _, new in new }
x.nextAccountIndex = AccumulateContext.check(
i: bump(i: x.nextAccountIndex),
serviceAccounts: x.accumulateState.newServiceAccounts
)
} else if codeHash == nil {
state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.OOB.rawValue)
} else {
Expand Down Expand Up @@ -445,8 +448,8 @@ public class Transfer: HostCall {

let destAcc: ServiceAccountDetails? = if try await x.serviceAccounts.get(serviceAccount: dest) != nil {
try await x.serviceAccounts.get(serviceAccount: dest)
} else if x.accumulateState.serviceAccounts[dest] != nil {
x.accumulateState.serviceAccounts[dest]?.toDetails()
} else if x.accumulateState.newServiceAccounts[dest] != nil {
x.accumulateState.newServiceAccounts[dest]?.toDetails()
} else {
nil
}
Expand Down Expand Up @@ -474,64 +477,107 @@ public class Transfer: HostCall {
}
}

/// Quit (remove) a service account
public class Quit: HostCall {
/// Eject (remove) a service account
public class Eject: HostCall {
public static var identifier: UInt8 { 12 }

public var x: AccumlateResultContext
public let timeslot: TimeslotIndex

public init(x: inout AccumlateResultContext) {
public init(x: inout AccumlateResultContext, timeslot: TimeslotIndex) {
self.x = x
self.timeslot = timeslot
}

public func _callImpl(config: ProtocolConfigRef, state: VMState) async throws {
let (dest, startAddr): (UInt64, UInt64) = state.readRegister(Registers.Index(raw: 7), Registers.Index(raw: 8))
let acc = try await x.serviceAccounts.get(serviceAccount: x.serviceIndex).expect("service account not found")
let amount = acc.balance - acc.thresholdBalance(config: config) + Balance(config.value.serviceMinBalance)
let gasLimit = Gas(state.getGas())

let isValidDest = dest == x.serviceIndex || dest == UInt64.max
let memoData = try? state.readMemory(address: startAddr, length: config.value.transferMemoSize)
let memo = memoData != nil ? try JamDecoder.decode(Data128.self, from: memoData!) : nil
let destination = ServiceIndex(truncatingIfNeeded: dest)

let destAcc: ServiceAccountDetails? = if try await x.serviceAccounts.get(serviceAccount: destination) != nil {
try await x.serviceAccounts.get(serviceAccount: destination)
} else if x.accumulateState.serviceAccounts[destination] != nil {
x.accumulateState.serviceAccounts[destination]?.toDetails()
let (reg7, reg8): (UInt64, UInt64) = state.readRegister(Registers.Index(raw: 7), Registers.Index(raw: 8))
let ejectIndex = ServiceIndex(truncatingIfNeeded: reg7)
let preimageHash = try? state.readMemory(address: reg8, length: 32)
let ejectAccount: ServiceAccountDetails? = if ejectIndex == x.serviceIndex {
nil
} else if try await x.serviceAccounts.get(serviceAccount: ejectIndex) != nil {
try await x.serviceAccounts.get(serviceAccount: ejectIndex)
} else if x.accumulateState.newServiceAccounts[ejectIndex] != nil {
x.accumulateState.newServiceAccounts[ejectIndex]?.toDetails()
} else {
nil
}
let minHoldPeriod = TimeslotIndex(config.value.preimagePurgePeriod)

if isValidDest {
state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.OK.rawValue)
x.serviceAccounts.set(serviceAccount: x.serviceIndex, account: nil)
throw VMInvocationsError.forceHalt
} else if memo == nil {
if preimageHash == nil {
state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.OOB.rawValue)
} else if destAcc == nil {
} else if ejectAccount == nil || ejectAccount?.codeHash.data != Data(x.serviceIndex.encode(method: .fixedWidth(32))) {
state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.WHO.rawValue)
} else if gasLimit < destAcc!.minOnTransferGas {
state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.LOW.rawValue)
} else {
}

let preimageInfo = try await x.serviceAccounts.get(
serviceAccount: ejectIndex,
preimageHash: Data32(preimageHash!)!,
length: max(81, UInt32(ejectAccount!.totalByteLength)) - 81
)

if ejectAccount!.itemsCount != 2 || preimageInfo == nil {
state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.HUH.rawValue)
} else if preimageInfo!.count == 2, preimageInfo![1] < timeslot - minHoldPeriod {
var destAccount = try await x.serviceAccounts.get(serviceAccount: x.serviceIndex)
destAccount?.balance += ejectAccount!.balance
x.serviceAccounts.set(serviceAccount: ejectIndex, account: nil)
x.serviceAccounts.set(serviceAccount: x.serviceIndex, account: destAccount)
state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.OK.rawValue)
// TODO: need to remove all storage and preimages?
x.serviceAccounts.set(serviceAccount: x.serviceIndex, account: nil)
x.transfers.append(DeferredTransfers(
sender: x.serviceIndex,
destination: destination,
amount: amount,
memo: memo!,
gasLimit: gasLimit
))
throw VMInvocationsError.forceHalt
} else {
state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.HUH.rawValue)
}
}
}

/// Query preimage info
public class Query: HostCall {
public static var identifier: UInt8 { 13 }

public var x: AccumlateResultContext

public init(x: inout AccumlateResultContext) {
self.x = x
}

public func _callImpl(config _: ProtocolConfigRef, state: VMState) async throws {
let (startAddr, length): (UInt32, UInt32) = state.readRegister(Registers.Index(raw: 7), Registers.Index(raw: 8))
let preimageHash = try? state.readMemory(address: startAddr, length: 32)
if preimageHash == nil {
state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.OOB.rawValue)
return
}

let preimageInfo = try await x.serviceAccounts.get(
serviceAccount: x.serviceIndex,
preimageHash: Data32(preimageHash!)!,
length: length
)
if preimageInfo == nil {
state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.NONE.rawValue)
state.writeRegister(Registers.Index(raw: 8), 0)
return
}

if preimageInfo!.isEmpty {
state.writeRegister(Registers.Index(raw: 7), 0)
state.writeRegister(Registers.Index(raw: 8), 0)
} else if preimageInfo!.count == 1 {
state.writeRegister(Registers.Index(raw: 7), 1 + (1 << 32) * preimageInfo![0])
state.writeRegister(Registers.Index(raw: 8), 0)
} else if preimageInfo!.count == 2 {
state.writeRegister(Registers.Index(raw: 7), 2 + (1 << 32) * preimageInfo![0])
state.writeRegister(Registers.Index(raw: 8), preimageInfo![1])
} else if preimageInfo!.count == 3 {
state.writeRegister(Registers.Index(raw: 7), 3 + (1 << 32) * preimageInfo![0])
state.writeRegister(Registers.Index(raw: 8), preimageInfo![1] + (1 << 32) * preimageInfo![2])
}
}
}

/// Solicit data to be made available in-core (through preimage lookups)
public class Solicit: HostCall {
public static var identifier: UInt8 { 13 }
public static var identifier: UInt8 { 14 }

public var x: AccumlateResultContext
public let timeslot: TimeslotIndex
Expand Down Expand Up @@ -571,7 +617,7 @@ public class Solicit: HostCall {

/// Forget data made available in-core (through preimage lookups)
public class Forget: HostCall {
public static var identifier: UInt8 { 14 }
public static var identifier: UInt8 { 15 }

public var x: AccumlateResultContext
public let timeslot: TimeslotIndex
Expand Down Expand Up @@ -613,9 +659,31 @@ public class Forget: HostCall {
}
}

/// Yield accumulation hash
public class Yield: HostCall {
public static var identifier: UInt8 { 16 }

public var x: AccumlateResultContext

public init(x: inout AccumlateResultContext) {
self.x = x
}

public func _callImpl(config _: ProtocolConfigRef, state: VMState) async throws {
let startAddr: UInt32 = state.readRegister(Registers.Index(raw: 7))
let hash = try? state.readMemory(address: startAddr, length: 32)
if hash == nil {
state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.OOB.rawValue)
} else {
state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.OK.rawValue)
x.yield = Data32(hash!)!
}
}
}

/// Historical lookup
public class HistoricalLookup: HostCall {
public static var identifier: UInt8 { 15 }
public static var identifier: UInt8 { 17 }

public let context: RefineContext.ContextType
public let service: ServiceIndex
Expand Down Expand Up @@ -672,7 +740,7 @@ public class HistoricalLookup: HostCall {

/// Import a segment to memory
public class Import: HostCall {
public static var identifier: UInt8 { 16 }
public static var identifier: UInt8 { 18 }

public let context: RefineContext.ContextType
public let importSegments: [Data]
Expand Down Expand Up @@ -709,7 +777,7 @@ public class Import: HostCall {

/// Export a segment from memory
public class Export: HostCall {
public static var identifier: UInt8 { 17 }
public static var identifier: UInt8 { 19 }

public var context: RefineContext.ContextType
public let exportSegmentOffset: UInt64
Expand Down Expand Up @@ -748,7 +816,7 @@ public class Export: HostCall {

/// Create an inner PVM
public class Machine: HostCall {
public static var identifier: UInt8 { 18 }
public static var identifier: UInt8 { 20 }

public var context: RefineContext.ContextType

Expand Down Expand Up @@ -777,7 +845,7 @@ public class Machine: HostCall {

/// Peek (read inner memory into outer memory)
public class Peek: HostCall {
public static var identifier: UInt8 { 19 }
public static var identifier: UInt8 { 21 }

public let context: RefineContext.ContextType

Expand Down Expand Up @@ -811,7 +879,7 @@ public class Peek: HostCall {

/// Poke (write outer memory into inner memory)
public class Poke: HostCall {
public static var identifier: UInt8 { 20 }
public static var identifier: UInt8 { 22 }

public var context: RefineContext.ContextType

Expand Down Expand Up @@ -845,7 +913,7 @@ public class Poke: HostCall {

/// Make some pages zero and writable in the inner PVM
public class Zero: HostCall {
public static var identifier: UInt8 { 21 }
public static var identifier: UInt8 { 23 }

public var context: RefineContext.ContextType

Expand All @@ -872,7 +940,7 @@ public class Zero: HostCall {

/// Make some pages zero and inaccessible in the inner PVM
public class VoidFn: HostCall {
public static var identifier: UInt8 { 22 }
public static var identifier: UInt8 { 24 }

public var context: RefineContext.ContextType

Expand Down Expand Up @@ -901,7 +969,7 @@ public class VoidFn: HostCall {

/// Invoke an inner PVM
public class Invoke: HostCall {
public static var identifier: UInt8 { 23 }
public static var identifier: UInt8 { 25 }

public var context: RefineContext.ContextType

Expand Down Expand Up @@ -960,7 +1028,7 @@ public class Invoke: HostCall {

/// Expunge an inner PVM
public class Expunge: HostCall {
public static var identifier: UInt8 { 24 }
public static var identifier: UInt8 { 26 }

public var context: RefineContext.ContextType

Expand Down Expand Up @@ -1050,8 +1118,8 @@ public class Log: HostCall {
public func _callImpl(config _: ProtocolConfigRef, state: VMState) async throws {
let regs: [UInt32] = state.readRegisters(in: 7 ..< 12)
let level = regs[0]
let target = regs[1] == 0 && regs[2] == 0 ? nil : try state.readMemory(address: regs[1], length: Int(regs[2]))
let message = try state.readMemory(address: regs[3], length: Int(regs[4]))
let target = regs[1] == 0 && regs[2] == 0 ? nil : try? state.readMemory(address: regs[1], length: Int(regs[2]))
let message = try? state.readMemory(address: regs[3], length: Int(regs[4]))

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH-mm-ss"
Expand All @@ -1061,7 +1129,7 @@ public class Log: HostCall {
time: time,
level: Level(rawValue: level) ?? .debug,
target: target,
message: message,
message: message ?? Data(),
core: core,
service: service
)
Expand Down
Loading

0 comments on commit 72f1411

Please sign in to comment.