diff --git a/lib/database/neo4j/queries/spendTransactionOutputs.js b/lib/database/neo4j/queries/spendTransactionOutputs.js index 2989fdc..085f924 100644 --- a/lib/database/neo4j/queries/spendTransactionOutputs.js +++ b/lib/database/neo4j/queries/spendTransactionOutputs.js @@ -10,33 +10,38 @@ const query = ` where address.id = thisOutput.address set address.writeLock = timestamp() with *, thisOutput.sources + [''] as pointers unwind [pointer in pointers | split(pointer, '::')] as pointer - optional match (address)-[output:Outputs]->(source:Transaction) - where source.id = pointer[0] and output.id = toInteger(pointer[1]) - and not (source)<-[:Sources {id: output.id}]-(:Transaction) set source.LOCKED = true - with countspace, params, collect(distinct source) as sources, - reduce(pointers = [], pointer in [output in params.outputs | - output.sources] | pointers + pointer) as reducedPointers, - collect(distinct source.id + '::' + output.id) as pointers + with *, [ + (address)-[output:Unspent]->(source:Transaction) + where source.id = pointer[0] and output.id = toInteger(pointer[1]) + and not (source)<-[:Sources {id: output.id}]-(:Transaction) + | {node: source, unspent: output} + ] as _sources + with countspace, params, reduce(S = [], s in collect(_sources) | S + s) as sources, + reduce(P = [], p in [output in params.outputs | output.sources] | P + p) as paramsPointers + with *, [source in sources | source.node] as sourceNodes, + [source in sources | source.unspent] as unspentOutputs create (transaction:Transaction {id: $id, time: timestamp()}) - foreach (_ in case when size(pointers)=size(reducedPointers) then [1] else [] end | + foreach (_ in case when size(unspentOutputs)=size(paramsPointers) then [1] else [] end | foreach (input in params.inputs | merge (transaction)-[:Inputs]->(:IOU {id: input.hash})) + foreach (unspent in unspentOutputs | delete unspent) foreach (output in params.outputs | foreach (pointer in [source in output.sources | split(source, '::')] | - foreach (funding in [source in sources where pointer[0] = source.id] | + foreach (funding in [source in sourceNodes where pointer[0] = source.id] | merge (transaction)-[:Sources {id: toInteger(pointer[1])}]->(funding))) ) foreach (output in params.outputs | merge (countspace)-[:Addresses]->(address:Address {id: output.address}) merge (address)-[:Outputs {id: toInteger(output.index)}]->(transaction) + merge (address)-[:Unspent {id: toInteger(output.index)}]->(transaction) ) ) - foreach (source in sources | remove source.LOCKED) + foreach (source in sources | remove source.node.LOCKED) with transaction, transaction.id as id, countspace.id as symbol, params, [(transaction)-[input:Inputs]->(iou) | iou.id] as inputs, [(transaction)-[source:Sources]->(funding) | funding.id + '::' + source.id] as sources, - [(transaction)<-[output:Outputs]-(address) | address.id + '::' + output.id] as newputs + [(transaction)<-[output:Unspent]-(address) | address.id + '::' + output.id] as newputs return id, symbol, inputs, sources, [output in params.outputs where (output.address + '::' + toInteger(output.index)) in newputs | output] as outputs `