Skip to content

Commit

Permalink
more fix
Browse files Browse the repository at this point in the history
  • Loading branch information
xlc committed Nov 7, 2024
1 parent 5cdfc1b commit f6c08eb
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 18 deletions.
4 changes: 3 additions & 1 deletion Blockchain/Sources/Blockchain/Blockchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ public final class Blockchain: ServiceBase, @unchecked Sendable {

let runtime = Runtime(config: config)
let parent = try await dataProvider.getState(hash: block.header.parentHash)
let stateRoot = await parent.value.stateRoot
let timeslot = timeProvider.getTime().timeToTimeslot(config: config)
// TODO: figure out what is the best way to deal with block received a bit too early
let state = try await runtime.apply(block: block, state: parent, context: .init(timeslot: timeslot + 1))
let context = Runtime.ApplyContext(timeslot: timeslot + 1, stateRoot: stateRoot)
let state = try await runtime.apply(block: block, state: parent, context: context)

try await dataProvider.blockImported(block: block, state: state)

Expand Down
6 changes: 4 additions & 2 deletions Blockchain/Sources/Blockchain/RuntimeProtocols/Runtime.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@ public final class Runtime {

public struct ApplyContext {
public let timeslot: TimeslotIndex
public let stateRoot: Data32

public init(timeslot: TimeslotIndex) {
public init(timeslot: TimeslotIndex, stateRoot _: Data32) {
self.timeslot = timeslot
stateRoot = Data32()
}
}

Expand All @@ -54,7 +56,7 @@ public final class Runtime {
throw Error.invalidParentHash
}

guard block.header.priorStateRoot == state.stateRoot else {
guard block.header.priorStateRoot == context.stateRoot else {
throw Error.invalidHeaderStateRoot
}

Expand Down
16 changes: 11 additions & 5 deletions Blockchain/Sources/Blockchain/State/State.swift
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,18 @@ public struct State: Sendable {
}
}

public func save() async throws {
// TODO: we don't really want to write to the underlying backend here
// instead, it should be writting to a in memory layer
// and when actually saving the state, save the in memory layer to the presistent store
public func save() async throws -> Data32 {
try await backend.write(layer.toKV())
return await backend.rootHash
}

public var stateRoot: Data32 {
get async {
await backend.rootHash
}
}
}

Expand Down Expand Up @@ -428,8 +438,4 @@ public class StateRef: Ref<State>, @unchecked Sendable {
public static func dummy(config: ProtocolConfigRef, block: BlockRef?) -> StateRef {
StateRef(State.dummy(config: config, block: block))
}

public var stateRoot: Data32 {
fatalError("not implemented")
}
}
5 changes: 5 additions & 0 deletions Blockchain/Sources/Blockchain/State/StateBackend.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ public final class StateBackend: Sendable {
try await trie.save()
}

public func writeRaw(_ values: [(key: Data32, value: Data?)]) async throws {
try await trie.update(values)
try await trie.save()
}

public func gc() async throws {
try await impl.gc { data in
guard data.count == 64 else {
Expand Down
4 changes: 3 additions & 1 deletion Blockchain/Sources/Blockchain/Validator/BlockAuthor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,11 @@ public final class BlockAuthor: ServiceBase2, @unchecked Sendable {
extrinsics: extrinsic.tickets
)

let stateRoot = try await state.value.save()

let unsignedHeader = Header.Unsigned(
parentHash: parentHash,
priorStateRoot: state.stateRoot,
priorStateRoot: stateRoot,
extrinsicsHash: extrinsic.hash(),
timeslot: timeslot,
epoch: safroleResult.epochMark,
Expand Down
15 changes: 12 additions & 3 deletions Blockchain/Tests/BlockchainTests/BlockAuthorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ struct BlockAuthorTests {
let block = try await blockAuthor.createNewBlock(timeslot: timeslot, claim: .right(pubkey))

// Verify block
try _ = await runtime.apply(block: block, state: genesisState, context: .init(timeslot: timeslot + 1))
try _ = await runtime.apply(block: block, state: genesisState, context: .init(
timeslot: timeslot + 1,
stateRoot: genesisState.value.stateRoot
))
}

@Test
Expand Down Expand Up @@ -95,7 +98,10 @@ struct BlockAuthorTests {
let block = try await blockAuthor.createNewBlock(timeslot: timeslot, claim: .left((ticket, devKey.bandersnatch)))

// Verify block
try _ = await runtime.apply(block: block, state: newStateRef, context: .init(timeslot: timeslot + 1))
try _ = await runtime.apply(block: block, state: newStateRef, context: .init(
timeslot: timeslot + 1,
stateRoot: newStateRef.value.stateRoot
))
}

@Test
Expand All @@ -122,7 +128,10 @@ struct BlockAuthorTests {
let timeslot = timeProvider.getTime().timeToTimeslot(config: config)

// Verify block
try _ = await runtime.apply(block: block.block, state: genesisState, context: .init(timeslot: timeslot + 1))
try _ = await runtime.apply(block: block.block, state: genesisState, context: .init(
timeslot: timeslot + 1,
stateRoot: genesisState.value.stateRoot
))
}

// TODO: test including extrinsic tickets from extrinsic pool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,11 @@ struct BlockchainDataProviderTests {

// Verify state exists
#expect(try await provider.hasState(hash: block.hash))
#expect(try await provider.getState(hash: block.hash).stateRoot == state.stateRoot)
#expect(try await provider.getState(hash: block.hash).value.stateRoot == state.value.stateRoot)

// Test getting best state
let bestState = try await provider.getBestState()
#expect(bestState.stateRoot == state.stateRoot)
#expect(await bestState.value.stateRoot == state.value.stateRoot)
}

@Test func testStateOperationsErrors() async throws {
Expand Down
6 changes: 4 additions & 2 deletions Node/Sources/Node/Genesis.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ extension Genesis {
let config = preset.config
let (state, block) = try State.devGenesis(config: config)
var kv = [String: Data]()
for (key, value) in try await state.value.toKV() {
kv[key.toHexString()] = value
for (key, value) in state.value.layer.toKV() {
if let value {
kv[key.encode().toHexString()] = try JamEncoder.encode(value)
}
}
return try ChainSpec(
name: preset.rawValue,
Expand Down
4 changes: 2 additions & 2 deletions Node/Sources/Node/Node.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ public class Node {
let chainspec = try await genesis.load()
let genesisBlock = try chainspec.getBlock()
let genesisStateData = try chainspec.getState()
let rootHash = try stateMerklize(kv: genesisStateData)
let backend = try StateBackend(InMemoryBackend(store: genesisStateData), config: chainspec.getConfig(), rootHash: rootHash)
let backend = try StateBackend(InMemoryBackend(), config: chainspec.getConfig(), rootHash: Data32())
try await backend.writeRaw(Array(genesisStateData))
let genesisState = try await State(backend: backend)
let genesisStateRef = StateRef(genesisState)
let protocolConfig = try chainspec.getConfig()
Expand Down

0 comments on commit f6c08eb

Please sign in to comment.