Fixed fixed encoding, inputs/outputs parsing

This commit is contained in:
Yuriy Glukhov 2019-09-05 20:35:21 +03:00 committed by zah
parent 58d78cfa7f
commit 817c819847
3 changed files with 46 additions and 119 deletions

View File

@ -52,7 +52,7 @@ contract MetaCoin {
contract(MetaCoin):
proc sendCoin(receiver: Address, amount: Uint256): Bool
proc getBalance(address: Address): Uint256 {.view.}
proc Transfer(fromAddr: indexed[Address], toAddr: indexed[Address], value: Uint256) {.event.}
proc Transfer(fromAddr, toAddr: indexed[Address], value: Uint256) {.event.}
proc BlaBla(fromAddr: indexed[Address]) {.event.}
const MetaCoinCode = "608060405234801561001057600080fd5b5032600090815260208190526040902061271090556101c2806100346000396000f30060806040526004361061004b5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166390b98a118114610050578063f8b2cb4f14610095575b600080fd5b34801561005c57600080fd5b5061008173ffffffffffffffffffffffffffffffffffffffff600435166024356100d5565b604080519115158252519081900360200190f35b3480156100a157600080fd5b506100c373ffffffffffffffffffffffffffffffffffffffff6004351661016e565b60408051918252519081900360200190f35b336000908152602081905260408120548211156100f457506000610168565b336000818152602081815260408083208054879003905573ffffffffffffffffffffffffffffffffffffffff871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a35060015b92915050565b73ffffffffffffffffffffffffffffffffffffffff16600090815260208190526040902054905600a165627a7a72305820000313ec0ebbff4ffefbe79d615d0ab019d8566100c40eb95a4eee617a87d1090029"

File diff suppressed because one or more lines are too long

147
web3.nim
View File

@ -138,7 +138,9 @@ func decode*[N](input: string, offset: int, to: var Stint[N]): int =
meaningfulLen
func fixedEncode(a: openarray[byte]): EncodeResult =
result = (dynamic: false, data: "00".repeat(32 - a.len mod 32) & byteutils.toHex(a))
var padding = a.len mod 32
if padding != 0: padding = 32 - padding
result = (dynamic: false, data: "00".repeat(padding) & byteutils.toHex(a))
func encode*[N](b: FixedBytes[N]): EncodeResult = fixedEncode(array[N, byte](b))
func encode*(b: Address): EncodeResult = fixedEncode(array[20, byte](b))
@ -175,7 +177,8 @@ func fromHex*(x: type Address, s: string): Address {.inline.} =
func decodeFixed(input: string, offset: int, to: var openarray[byte]): int =
let meaningfulLen = to.len * 2
let padding = (32 - to.len mod 32) * 2
var padding = to.len mod 32
if padding != 0: padding = (32 - padding) * 2
let offset = offset + padding
fromHexAux(input[offset .. offset + meaningfulLen - 1], to)
meaningfulLen + padding
@ -219,7 +222,7 @@ template typeSignature(T: typedesc): string =
elif T is DynamicBytes:
"bytes"
elif T is FixedBytes:
"byte" & $T.N
"bytes" & $T.N
elif T is StUint:
"uint" & $T.bits
elif T is Address:
@ -369,23 +372,13 @@ type
function, constructor, event
MutabilityKind = enum
pure, view, nonpayable, payable
SequenceKind = enum
single, fixed, dynamic
FunctionInputOutput = object
name: string
typ: string
case sequenceKind: SequenceKind
of single, dynamic: discard
of fixed:
count: int
typ: NimNode
EventInput = object
name: string
typ: string
typ: NimNode
indexed: bool
case sequenceKind: SequenceKind
of single, dynamic: discard
of fixed:
count: int
FunctionObject = object
name: string
stateMutability: MutabilityKind
@ -412,7 +405,7 @@ proc getSignature(function: FunctionObject | EventObject): NimNode =
result = newCall(bindSym"joinStrings")
result.add(newLit(function.name & "("))
for i, input in function.inputs:
result.add(newCall(bindSym"typeSignature", ident input.typ))
result.add(newCall(bindSym"typeSignature", input.typ))
if i != function.inputs.high:
result.add(newLit(","))
result.add(newLit(")"))
@ -432,90 +425,40 @@ proc addAddressAndSignatureToOptions(options: JsonNode, address: Address, signat
proc parseContract(body: NimNode): seq[InterfaceObject] =
proc parseOutputs(outputNode: NimNode): seq[FunctionInputOutput] =
#if outputNode.kind == nnkIdent:
# result.add FunctionInputOutput(
# name: "",
# typ: $outputNode.ident
# )
case outputNode.kind:
of nnkBracketExpr:
result.add FunctionInputOutput(
name: "",
typ: $outputNode[0].ident,
sequenceKind: if outputNode.len == 1:
dynamic
else:
fixed
)
if outputNode.len == 2:
result[^1].count = outputNode[1].intVal.int
of nnkIdent:
result.add FunctionInputOutput(
name: "",
typ: $outputNode.ident,
sequenceKind: single
)
else:
discard
result.add FunctionInputOutput(typ: (if outputNode.kind == nnkEmpty: ident"void" else: outputNode))
proc parseInputs(inputNodes: NimNode): seq[FunctionInputOutput] =
for i in 1..<inputNodes.len:
let input = inputNodes[i]
if input.kind == nnkIdentDefs:
when defined(debug):
echo input.repr
# echo input.treerepr
if input[1].kind == nnkBracketExpr:
result.add FunctionInputOutput(
name: $input[0].ident,
typ: $input[1][0].ident,
sequenceKind: if input[1].len == 1:
dynamic
else:
fixed
)
if input[1].len == 2:
result[^1].count = input[1][1].intVal.int
else:
result.add FunctionInputOutput(
name: $input[0].ident,
typ: $input[1].ident,
sequenceKind: single
)
input.expectKind(nnkIdentDefs)
let typ = input[^2]
for j in 0 .. input.len - 3:
let arg = input[j]
result.add(FunctionInputOutput(
name: $arg,
typ: typ,
))
proc parseEventInputs(inputNodes: NimNode): seq[EventInput] =
for i in 1..<inputNodes.len:
let input = inputNodes[i]
if input.kind == nnkIdentDefs:
case input[1].kind:
of nnkIdent:
result.add EventInput(
name: $input[0].ident,
typ: $input[1].ident,
indexed: false
)
input.expectKind(nnkIdentDefs)
let typ = input[^2]
for j in 0 .. input.len - 3:
let arg = input[j]
case typ.kind:
of nnkBracketExpr:
#doAssert($input[1][0].ident == "indexed",
# "Only `indexed` is allowed as option for event inputs")
if $input[1][0].ident == "indexed":
if $typ[0] == "indexed":
result.add EventInput(
name: $input[0].ident,
typ: $input[1][1].ident,
name: $arg,
typ: typ[1],
indexed: true
)
else:
result.add EventInput(
name: $input[0].ident,
typ: $input[1][0].ident,
indexed: false,
sequenceKind: if input[1].len == 1:
dynamic
else:
fixed
)
if input[1].len != 1:
result[^1].count = input[1][1].intVal.int
result.add EventInput(name: $arg, typ: typ)
else:
doAssert(false,
"Can't have anything but ident or bracket expression here")
result.add EventInput(name: $arg, typ: typ)
when defined(debug):
echo body.treeRepr
var
@ -599,7 +542,7 @@ macro contract*(cname: untyped, body: untyped): untyped =
output = if obj.functionObject.outputs.len != 1:
ident "void"
else:
ident obj.functionObject.outputs[0].typ
obj.functionObject.outputs[0].typ
var
encodedParams = genSym(nskVar)#newLit("")
offset = genSym(nskVar)
@ -619,13 +562,8 @@ macro contract*(cname: untyped, body: untyped): untyped =
`offset` += (if encoding.dynamic:
32
else:
encoding.data.len)
encoding.data.len div 2)
`encodings`.add encoding
#encodedParams = nnkInfix.newTree(
# ident "&",
# encodedParams,
# nnkCall.newTree(ident "encode", ident input.name)
#)
encoder.add quote do:
for encoding in `encodings`:
if encoding.dynamic:
@ -642,20 +580,7 @@ macro contract*(cname: untyped, body: untyped): untyped =
for input in obj.functionObject.inputs:
procDef[3].add nnkIdentDefs.newTree(
ident input.name,
(case input.sequenceKind:
of single: ident input.typ
of dynamic: nnkBracketExpr.newTree(ident "seq", ident input.typ)
of fixed:
nnkBracketExpr.newTree(
ident "array",
nnkInfix.newTree(
ident "..",
newLit(0),
newLit(input.count)
),
ident input.typ
)
),
input.typ,
newEmptyNode()
)
procDef[6].add quote do:
@ -686,14 +611,14 @@ macro contract*(cname: untyped, body: untyped): untyped =
for input in obj.eventObject.inputs:
let param = nnkIdentDefs.newTree(
ident input.name,
ident input.typ,
input.typ,
newEmptyNode()
)
params.add param
paramsWithRawData.add param
let
argument = genSym(nskVar)
kind = ident input.typ
kind = input.typ
if input.indexed:
argParseBody.add quote do:
var `argument`: `kind`