Skip to content

Commit b57478e

Browse files
authored
fix and debug (#349)
* fix release * hostcall fix, add some tests from fuzz reports * fix mod * fix and more tests * add more tests * remove extra files * fix lint * add tests * fix
1 parent 95cde61 commit b57478e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+7208
-37
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
- run: sudo apt-get update
2828
- uses: awalsh128/cache-apt-pkgs-action@latest
2929
with:
30-
packages: librocksdb-dev libzstd-dev libbz2-dev liblz4-dev
30+
packages: curl build-essential cmake librocksdb-dev libzstd-dev libbz2-dev liblz4-dev
3131
- uses: aws-actions/configure-aws-credentials@v4
3232
with:
3333
aws-region: us-east-2

Blockchain/Sources/Blockchain/RuntimeProtocols/Accumulation.swift

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ extension Accumulation {
212212
var newAuthorizationQueue = authorizationQueue
213213
var overallAccountChanges = AccountChanges()
214214
var tempPrivilegedServices: PrivilegedServices?
215-
var newDelegator = privilegedServices.delegator
216-
var newAssigners = privilegedServices.assigners
215+
var newDelegator: ServiceIndex?
216+
var newAssigners: ConfigFixedSizeArray<ServiceIndex, ProtocolConfig.TotalNumberOfCores>?
217217

218218
for report in workReports {
219219
for digest in report.digests {
@@ -260,20 +260,19 @@ extension Accumulation {
260260

261261
servicePreimageSet.formUnion(singleOutput.provide)
262262

263-
switch service {
264263
// m'
265-
case privilegedServices.manager:
264+
if service == privilegedServices.manager {
266265
tempPrivilegedServices = PrivilegedServices(
267266
manager: singleOutput.state.manager,
268267
assigners: singleOutput.state.assigners,
269268
delegator: singleOutput.state.delegator,
270269
alwaysAcc: singleOutput.state.alwaysAcc
271270
)
271+
}
272+
272273
// i'
273-
case privilegedServices.delegator:
274+
if service == privilegedServices.delegator {
274275
newValidatorQueue = singleOutput.state.validatorQueue
275-
default:
276-
break
277276
}
278277

279278
// v'
@@ -288,7 +287,10 @@ extension Accumulation {
288287

289288
// a'
290289
if let index = tempPrivilegedServices?.assigners.firstIndex(of: service) {
291-
newAssigners[index] = singleOutput.state.assigners[index]
290+
if newAssigners == nil {
291+
newAssigners = tempPrivilegedServices?.assigners
292+
}
293+
newAssigners![index] = singleOutput.state.assigners[index]
292294
}
293295

294296
accountsRef = singleOutput.state.accounts
@@ -308,8 +310,8 @@ extension Accumulation {
308310
validatorQueue: newValidatorQueue ?? validatorQueue,
309311
authorizationQueue: newAuthorizationQueue,
310312
manager: tempPrivilegedServices?.manager ?? privilegedServices.manager,
311-
assigners: newAssigners,
312-
delegator: newDelegator,
313+
assigners: newAssigners ?? tempPrivilegedServices?.assigners ?? privilegedServices.assigners,
314+
delegator: newDelegator ?? tempPrivilegedServices?.delegator ?? privilegedServices.delegator,
313315
alwaysAcc: tempPrivilegedServices?.alwaysAcc ?? privilegedServices.alwaysAcc,
314316
entropy: state.entropy
315317
),
@@ -533,15 +535,6 @@ extension Accumulation {
533535
timeslot: timeslot
534536
)
535537

536-
authorizationQueue = accumulateOutput.state.authorizationQueue
537-
validatorQueue = accumulateOutput.state.validatorQueue
538-
privilegedServices = PrivilegedServices(
539-
manager: accumulateOutput.state.manager,
540-
assigners: accumulateOutput.state.assigners,
541-
delegator: accumulateOutput.state.delegator,
542-
alwaysAcc: accumulateOutput.state.alwaysAcc
543-
)
544-
545538
// transfers execution + transfers statistics
546539
var transferGroups = [ServiceIndex: [DeferredTransfers]]()
547540
var transfersStats = TransfersStats()
@@ -552,7 +545,7 @@ extension Accumulation {
552545
let gasUsed = try await onTransfer(
553546
config: config,
554547
serviceIndex: service,
555-
serviceAccounts: accountsMutRef,
548+
serviceAccounts: accumulateOutput.state.accounts,
556549
timeslot: timeslot,
557550
entropy: entropy,
558551
transfers: transfers
@@ -564,6 +557,16 @@ extension Accumulation {
564557

565558
self = accumulateOutput.state.accounts.value as! Self
566559

560+
// update non-accounts state after accounts updated
561+
authorizationQueue = accumulateOutput.state.authorizationQueue
562+
validatorQueue = accumulateOutput.state.validatorQueue
563+
privilegedServices = PrivilegedServices(
564+
manager: accumulateOutput.state.manager,
565+
assigners: accumulateOutput.state.assigners,
566+
delegator: accumulateOutput.state.delegator,
567+
alwaysAcc: accumulateOutput.state.alwaysAcc
568+
)
569+
567570
// update accumulation history
568571
let accumulated = accumulatableReports[0 ..< accumulateOutput.numAccumulated]
569572
let newHistoryItem = Set(accumulated.map(\.packageSpecification.workPackageHash))

Blockchain/Sources/Blockchain/State/ServiceAccounts.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,12 @@ public class ServiceAccountsMutRef {
6565
}
6666

6767
public func addNew(serviceAccount index: ServiceIndex, account: ServiceAccount) async throws {
68-
ref.value.set(serviceAccount: index, account: account.toDetails())
68+
// set new account details with zero footprint initially
69+
var accountDetails = account.toDetails()
70+
accountDetails.itemsCount = 0
71+
accountDetails.totalByteLength = 0
72+
ref.value.set(serviceAccount: index, account: accountDetails)
73+
6974
for (key, value) in account.storage {
7075
try await ref.value.set(serviceAccount: index, storageKey: key, value: value)
7176
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
public let serviceIndexModValue = UInt32((1 << 32) - (1 << 9))
1+
public let serviceIndexModValue = UInt32(UInt64(1) << 32 - (1 << 9))

Blockchain/Sources/Blockchain/VMInvocations/HostCall/HostCalls.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,13 +225,16 @@ public class Lookup: HostCall {
225225
}
226226

227227
let preimageHash = try Data32(state.readMemory(address: regs[0], length: 32))
228+
logger.debug("preimageHash: \(String(describing: preimageHash))")
228229

229230
let value: Data? = if let service, let preimageHash {
230231
try await serviceAccounts.value.get(serviceAccount: service, preimageHash: preimageHash)
231232
} else {
232233
nil
233234
}
234235

236+
logger.debug("value: \(String(describing: value))")
237+
235238
let reg10: UInt64 = state.readRegister(Registers.Index(raw: 10))
236239
let reg11: UInt64 = state.readRegister(Registers.Index(raw: 11))
237240

@@ -774,7 +777,8 @@ public class Bless: HostCall {
774777
if state.isMemoryReadable(address: regs[1], length: 4 * config.value.totalNumberOfCores) {
775778
assigners = try JamDecoder.decode(
776779
ConfigFixedSizeArray<ServiceIndex, ProtocolConfig.TotalNumberOfCores>.self,
777-
from: state.readMemory(address: regs[1], length: 4 * config.value.totalNumberOfCores)
780+
from: state.readMemory(address: regs[1], length: 4 * config.value.totalNumberOfCores),
781+
withConfig: config
778782
)
779783
}
780784

@@ -797,6 +801,11 @@ public class Bless: HostCall {
797801
} else if ![regs[0], regs[2]].allSatisfy({ $0 >= 0 && $0 <= Int(UInt32.max) }) {
798802
state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.WHO.rawValue)
799803
} else {
804+
logger.debug("manager: \(regs[0])")
805+
logger.debug("assigners: \(String(describing: assigners))")
806+
logger.debug("delegator: \(regs[2])")
807+
logger.debug("alwaysAcc: \(String(describing: alwaysAcc))")
808+
800809
state.writeRegister(Registers.Index(raw: 7), HostCallResultCode.OK.rawValue)
801810
x.state.manager = regs[0]
802811
x.state.assigners = assigners!
@@ -919,7 +928,7 @@ public class New: HostCall {
919928
}
920929

921930
private func bump(i: ServiceIndex) -> ServiceIndex {
922-
256 + ((i - 256 + 42) & (serviceIndexModValue - 1))
931+
256 + ((i - 256 + 42) % serviceIndexModValue)
923932
}
924933

925934
public func _callImpl(config: ProtocolConfigRef, state: VMState) async throws {

Blockchain/Sources/Blockchain/VMInvocations/Invocations/AccumulateInvocation.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ public func accumulate(
3131
return .init(state: state, transfers: [], commitment: nil, gasUsed: Gas(0), provide: [])
3232
}
3333

34-
let initialIndex = try Blake2b256.hash(JamEncoder.encode(UInt(serviceIndex), state.entropy, UInt(timeslot))).data.decode(UInt32.self)
34+
let initialIndex = try Blake2b256.hash(JamEncoder.encode(serviceIndex, state.entropy, timeslot)).data.decode(UInt32.self)
3535
let nextAccountIndex = try await AccumulateContext.check(
36-
i: initialIndex % serviceIndexModValue + 256,
36+
i: (initialIndex % serviceIndexModValue) + 256,
3737
accounts: state.accounts.toRef()
3838
)
3939

Blockchain/Sources/Blockchain/VMInvocations/Invocations/OnTransferInvocation.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,23 @@ public func onTransfer(
1212
transfers: [DeferredTransfers]
1313
) async throws -> Gas {
1414
guard var account = try await serviceAccounts.value.get(serviceAccount: serviceIndex),
15-
let preimage = try await serviceAccounts.value.get(serviceAccount: serviceIndex, preimageHash: account.codeHash),
1615
!transfers.isEmpty
1716
else {
1817
return Gas(0)
1918
}
2019

21-
let codeBlob = try CodeAndMeta(data: preimage).codeBlob
20+
account.balance += transfers.reduce(Balance(0)) { $0 + $1.amount }
21+
serviceAccounts.set(serviceAccount: serviceIndex, account: account)
2222

23-
guard codeBlob.count <= config.value.maxServiceCodeSize else {
23+
guard let preimage = try await serviceAccounts.value.get(serviceAccount: serviceIndex, preimageHash: account.codeHash) else {
2424
return Gas(0)
2525
}
2626

27-
account.balance += transfers.reduce(Balance(0)) { $0 + $1.amount }
27+
let codeBlob = try CodeAndMeta(data: preimage).codeBlob
2828

29-
serviceAccounts.set(serviceAccount: serviceIndex, account: account)
29+
guard codeBlob.count <= config.value.maxServiceCodeSize else {
30+
return Gas(0)
31+
}
3032

3133
let contextContent = OnTransferContext.ContextType(serviceIndex: serviceIndex, accounts: serviceAccounts)
3234
let ctx = OnTransferContext(context: contextContent, config: config, entropy: entropy, transfers: transfers)

JAMTests/Package.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ let package = Package(
3535
.copy("../../jamtestvectors"),
3636
.copy("../../jamduna"),
3737
.copy("../../javajam"),
38+
.copy("../../other"),
3839
],
3940
swiftSettings: [
4041
.interoperabilityMode(.Cxx),

JAMTests/Sources/JAMTests/TestLoader.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ enum TestsSource: String {
3232
case jamduna
3333
case javajam
3434
case jamixir
35+
case other
3536
}
3637

3738
enum TestLoader {
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import Foundation
2+
import Testing
3+
import Utils
4+
5+
@testable import JAMTests
6+
7+
struct OtherTests {
8+
// empty array means run all
9+
static let testFilters: [(String, String)] = []
10+
11+
// ignore tests
12+
static let ignore: [(String, String)] = [
13+
("0.6.7/1754982630", "00000008"), // NOTE: seems this should fail on .invalidResultCodeHash
14+
]
15+
16+
static func discoverTests() throws -> [Testcase] {
17+
let otherPath = Bundle.module.resourcePath! + "/other"
18+
var allTestcases: [Testcase] = []
19+
20+
for version in try FileManager.default.contentsOfDirectory(atPath: otherPath).sorted() {
21+
guard !version.starts(with: ".") else { continue }
22+
23+
let versionPath = otherPath + "/" + version
24+
for timestamp in try FileManager.default.contentsOfDirectory(atPath: versionPath).sorted() {
25+
guard !timestamp.starts(with: ".") else { continue }
26+
27+
let path = "\(version)/\(timestamp)"
28+
29+
let testcases = try JamTestnet.loadTests(path: path, src: .other)
30+
31+
let testsExceptIgnore = testcases.filter { testcase in
32+
for (ignorePath, prefix) in ignore where path == ignorePath && testcase.description.starts(with: prefix) {
33+
return false
34+
}
35+
return true
36+
}
37+
38+
if testFilters.isEmpty {
39+
allTestcases.append(contentsOf: testsExceptIgnore)
40+
} else {
41+
for (filterPath, filterPrefix) in testFilters where filterPath == path {
42+
let filtered = testsExceptIgnore.filter { $0.description.starts(with: filterPrefix) }
43+
allTestcases.append(contentsOf: filtered)
44+
}
45+
}
46+
}
47+
}
48+
49+
return allTestcases
50+
}
51+
52+
@Test(arguments: try discoverTests())
53+
func otherTests(_ testcase: Testcase) async throws {
54+
try await TraceTest.test(testcase)
55+
}
56+
}

0 commit comments

Comments
 (0)