mirror of
https://github.com/luxfi/chains.git
synced 2026-09-24 00:26:00 +00:00
TestConsciousBlocks + cmd/conscious drive the REAL aivm ChainVM: block 1 (perception) imports a committed C-intent -> binds a staked operator committee under consensus; block 2 (cognition) commits the quorum-settled canonical AI decision (Proof-of-Thought) + receipt_root. Heights chain 0->1->2, canonical decision + receipt_root deterministic across runs. Added VM.FundLedger (node-internal genesis seam, fail-closed on non-MemLedger), MemLedger.Credit, Engine.TaskForIntent. 69 aivm tests green, -race clean.
97 lines
4.3 KiB
Go
97 lines
4.3 KiB
Go
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package aivm
|
|
|
|
// export.go is the A->C OUTBOUND seam: ExportReceipt produces, for a settled C
|
|
// intent, the canonical AInferenceReceipt and a Merkle proof that its
|
|
// receipt_hash is included under the engine's committed receipt_root. The C-side
|
|
// boundary (Blue-A's aivmbridge) admits the receipt by:
|
|
// 1. recomputing receipt_hash = keccak(DomainReceipt || receipt.Encode()),
|
|
// 2. checking VerifyReceiptProof(receipt_hash, proof, receipt_root) == true
|
|
// against the receipt_root it tracks for A-Chain.
|
|
// No A-Chain trust is imported beyond that single 32-byte root commitment.
|
|
//
|
|
// The receipt is RECONSTRUCTED deterministically from settled on-state (the task
|
|
// record + canonical result + selected/winner sets), so export is a pure read;
|
|
// it never re-runs settlement and cannot change state. The reconstructed receipt
|
|
// is byte-identical to the one emitted at Settle (same buildReceipt over the same
|
|
// immutable settled state), so its Hash() equals the stored leaf and the proof
|
|
// verifies.
|
|
|
|
import "github.com/luxfi/geth/common"
|
|
|
|
// TaskForIntent returns the A-Chain task id that a committed C-Chain intent
|
|
// created (zero hash if the intent never created a task). The task id is the
|
|
// engine-internal id derived at createTask (computeTaskID over the requester's
|
|
// nonce + height), distinct from the C-side intent id; this mapping is the only
|
|
// way an external caller (the C boundary, an RPC client, this package's drivers)
|
|
// resolves "the intent I committed" to "the task that answers it" for the
|
|
// lifecycle calls (SelectOperators / Commit / Reveal / Settle / GetTask) that key
|
|
// on the task id. Pure read.
|
|
func (e *Engine) TaskForIntent(st QuorumState, intentID common.Hash) common.Hash {
|
|
return st.GetState(slotHash(nsIntentTask, intentID))
|
|
}
|
|
|
|
// ExportReceipt returns the settled receipt for the given C-chain intent id and
|
|
// a proof of its inclusion under the current receipt_root. Errors if the intent
|
|
// has no settled receipt. The returned (receipt, proof, root) triple is exactly
|
|
// what the C boundary verifies.
|
|
func (e *Engine) ExportReceipt(st QuorumState, intentID common.Hash) (AInferenceReceipt, MerkleProof, common.Hash, error) {
|
|
// Locate the receipt leaf index for this intent (stored as index+1; 0 means
|
|
// unsettled / unknown).
|
|
idxPlus1 := readUint64(st, slotHash(nsIntentRcpt, intentID))
|
|
if idxPlus1 == 0 {
|
|
return AInferenceReceipt{}, MerkleProof{}, common.Hash{}, ErrReceiptNotFound
|
|
}
|
|
leafIndex := uint32(idxPlus1 - 1)
|
|
|
|
// Recover the task this intent created, then reconstruct the receipt.
|
|
taskID := st.GetState(slotHash(nsIntentTask, intentID))
|
|
if taskID == (common.Hash{}) {
|
|
return AInferenceReceipt{}, MerkleProof{}, common.Hash{}, ErrReceiptNotFound
|
|
}
|
|
receipt, err := e.reconstructReceipt(st, taskID)
|
|
if err != nil {
|
|
return AInferenceReceipt{}, MerkleProof{}, common.Hash{}, err
|
|
}
|
|
|
|
// Build the inclusion proof over the leaf-hashed receipt list and return the
|
|
// current root.
|
|
leaves := allReceiptLeaves(st)
|
|
if leafIndex >= uint32(len(leaves)) {
|
|
return AInferenceReceipt{}, MerkleProof{}, common.Hash{}, ErrProofOutOfRange
|
|
}
|
|
hashed := make([]common.Hash, len(leaves))
|
|
for i, lh := range leaves {
|
|
hashed[i] = leafHash(lh)
|
|
}
|
|
proof := merkleProof(hashed, leafIndex)
|
|
root := e.ReceiptRoot(st)
|
|
return receipt, proof, root, nil
|
|
}
|
|
|
|
// reconstructReceipt rebuilds the canonical receipt for a settled task purely
|
|
// from on-state — identical bytes to the receipt emitted at Settle.
|
|
func (e *Engine) reconstructReceipt(st QuorumState, taskID common.Hash) (AInferenceReceipt, error) {
|
|
task := readTask(st, taskID)
|
|
if task.Status == TaskNone || !isSet(st.GetState(slotHash(nsSettled, taskID))) {
|
|
return AInferenceReceipt{}, ErrTaskUnknown
|
|
}
|
|
feePaid := readUint(st, slotHash(nsTaskFee, taskID))
|
|
canonical := st.GetState(slotHash(nsCanonical, taskID))
|
|
height := readUint64(st, slotHash(nsTaskHeight, taskID))
|
|
|
|
res := SettleResult{Status: task.Status, CanonicalHash: canonical}
|
|
var winners []common.Address
|
|
if task.Status == TaskSettled {
|
|
revealers, hashes := tally(st, taskID)
|
|
for i := range revealers {
|
|
if hashes[i] == canonical {
|
|
winners = append(winners, revealers[i])
|
|
}
|
|
}
|
|
}
|
|
return e.buildReceipt(st, taskID, task, res, feePaid, height, winners), nil
|
|
}
|