Skip to content

Instantly share code, notes, and snippets.

@kayabaNerve
Created February 6, 2021 20:50
Show Gist options
  • Save kayabaNerve/a03fdc506a00069e81c29afc5d6816bb to your computer and use it in GitHub Desktop.
Save kayabaNerve/a03fdc506a00069e81c29afc5d6816bb to your computer and use it in GitHub Desktop.
parseSend supporting missing work.
import ../../../lib/[Errors, Hash]
import ../../../Wallet/Wallet
import ../../../Database/Transactions/objects/SendObj
import ../SerializeCommon
proc parseSend*(
sendStr: string,
diff: uint32,
allowMissingWork: bool = false
): Send {.forceCheck: [
ValueError,
Spam
].} =
#Verify the input length.
if sendStr.len < BYTE_LEN:
raise newLoggedException(ValueError, "parseSend not handed enough data to get the amount of inputs.")
let outputLenPos: int = BYTE_LEN + (int(sendStr[0]) * (HASH_LEN + BYTE_LEN))
if sendStr.len < outputLenPos + BYTE_LEN:
raise newLoggedException(ValueError, "parseSend not handed enough data to get the amount of outputs.")
var
#Inputs Length | Inputs | Outputs Length | Signature
sendSeq: seq[string] = sendStr.deserialize(
BYTE_LEN,
sendStr[0].fromBinary() * (HASH_LEN + BYTE_LEN),
BYTE_LEN,
sendStr[outputLenPos].fromBinary() * (ED_PUBLIC_KEY_LEN + MEROS_LEN),
ED_SIGNATURE_LEN
)
parsedLen: int = sendSeq.join("").len
#The way this is written also handles too large of a buffer.
hasWork: bool = (sendStr.len - parsedLen) == 0
if (not allowMissingWork) and (not hasWork):
raise newException(ValueError, "Send is incomplete.")
#Make sure the only difference is the work field.
if allowMissingWork and (not hasWork) and ((sendStr.len - parsedLen) != INT_LEN):
raise newException("While the work is allowed to be missing, even more is missing or additional data was provided.")
#Convert the inputs.
var inputs: seq[FundedInput] = newSeq[FundedInput](sendSeq[0].fromBinary())
if inputs.len == 0:
raise newLoggedException(ValueError, "parseSend handed a Send with no inputs.")
for i in countup(0, sendSeq[1].len - 1, 33):
inputs[i div 33] = newFundedInput(sendSeq[1][i ..< i + 32].toHash[:256](), sendSeq[1][i + 32].fromBinary())
#Convert the outputs.
var outputs: seq[SendOutput] = newSeq[SendOutput](sendSeq[2].fromBinary())
if outputs.len == 0:
raise newLoggedException(ValueError, "parseSend handed a Send with no outputs.")
for i in countup(0, sendSeq[3].len - 1, 40):
outputs[i div 40] = newSendOutput(
newEdPublicKey(sendSeq[3][i ..< i + 32]),
uint64(sendSeq[3][i + 32 ..< i + 40].fromBinary())
)
#Create the Send.
result = newSendObj(inputs, outputs)
result.hash = hash
result.signature = newEdSignature(sendSeq[4])
#Verify the Send isn't spam, if the Send has work.
if hasWork:
result.proof = cast[uint32](sendStr[sendStr.len - INT_LEN ..< sendStr.len].fromBinary())
result.argon = Argon(
Blake256("\2" & sendStr[0 ..< sendStr.len - (ED_SIGNATURE_LEN + INT_LEN)]).serialize(),
result.proof.toBinary(8)
)
if result.argon.overflows(result.getDifficultyFactor() * diff):
raise newSpam("Send didn't beat the difficulty.", hash, argon, factor * diff)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment