REST API: add ssz encoding for publishBlock (#4154)
This commit is contained in:
parent
af9ec577d0
commit
a845450283
|
@ -769,14 +769,18 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
|||
block:
|
||||
if contentBody.isNone():
|
||||
return RestApiResponse.jsonError(Http400, EmptyRequestBodyError)
|
||||
let body = contentBody.get()
|
||||
let res = decodeBody(RestPublishedSignedBeaconBlock, body)
|
||||
if res.isErr():
|
||||
return RestApiResponse.jsonError(Http400, InvalidBlockObjectError,
|
||||
$res.error())
|
||||
var forked = ForkedSignedBeaconBlock(res.get())
|
||||
let
|
||||
body = contentBody.get()
|
||||
version = request.headers.getString("eth-consensus-version")
|
||||
var
|
||||
restBlock = decodeBody(RestPublishedSignedBeaconBlock, body,
|
||||
version).valueOr:
|
||||
return RestApiResponse.jsonError(Http400, InvalidBlockObjectError,
|
||||
$error)
|
||||
forked = ForkedSignedBeaconBlock(restBlock)
|
||||
|
||||
if forked.kind != node.dag.cfg.blockForkAtEpoch(
|
||||
getForkedBlockField(forked, slot).epoch):
|
||||
getForkedBlockField(forked, slot).epoch):
|
||||
return RestApiResponse.jsonError(Http400, InvalidBlockObjectError)
|
||||
|
||||
withBlck(forked):
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import std/typetraits
|
||||
import std/[typetraits, strutils]
|
||||
import stew/[assign2, results, base10, byteutils], presto/common,
|
||||
libp2p/peerid, serialization, json_serialization,
|
||||
json_serialization/std/[options, net, sets],
|
||||
|
@ -85,7 +85,9 @@ type
|
|||
SignedBlindedBeaconBlock |
|
||||
SignedValidatorRegistrationV1 |
|
||||
SignedVoluntaryExit |
|
||||
Web3SignerRequest |
|
||||
Web3SignerRequest
|
||||
|
||||
EncodeOctetTypes* =
|
||||
altair.SignedBeaconBlock |
|
||||
bellatrix.SignedBeaconBlock |
|
||||
phase0.SignedBeaconBlock
|
||||
|
@ -2273,6 +2275,58 @@ proc parseRoot(value: string): Result[Eth2Digest, cstring] =
|
|||
except ValueError:
|
||||
err("Unable to decode root value")
|
||||
|
||||
proc decodeBody*(
|
||||
t: typedesc[RestPublishedSignedBeaconBlock],
|
||||
body: ContentBody,
|
||||
version: string
|
||||
): Result[RestPublishedSignedBeaconBlock, cstring] =
|
||||
if body.contentType == ApplicationJsonMediaType:
|
||||
let data =
|
||||
try:
|
||||
RestJson.decode(body.data, RestPublishedSignedBeaconBlock,
|
||||
requireAllFields = true,
|
||||
allowUnknownFields = true)
|
||||
except SerializationError as exc:
|
||||
debug "Failed to deserialize REST JSON data",
|
||||
err = exc.formatMsg("<data>"),
|
||||
data = string.fromBytes(body.data)
|
||||
return err("Unable to deserialize data")
|
||||
except CatchableError:
|
||||
return err("Unexpected deserialization error")
|
||||
ok(data)
|
||||
elif body.contentType == OctetStreamMediaType:
|
||||
let blockFork = ? BeaconBlockFork.decodeString(version)
|
||||
case blockFork
|
||||
of BeaconBlockFork.Phase0:
|
||||
let blck =
|
||||
try:
|
||||
SSZ.decode(body.data, phase0.SignedBeaconBlock)
|
||||
except SerializationError:
|
||||
return err("Unable to deserialize data")
|
||||
except CatchableError:
|
||||
return err("Unexpected deserialization error")
|
||||
ok(RestPublishedSignedBeaconBlock(ForkedSignedBeaconBlock.init(blck)))
|
||||
of BeaconBlockFork.Altair:
|
||||
let blck =
|
||||
try:
|
||||
SSZ.decode(body.data, altair.SignedBeaconBlock)
|
||||
except SerializationError:
|
||||
return err("Unable to deserialize data")
|
||||
except CatchableError:
|
||||
return err("Unexpected deserialization error")
|
||||
ok(RestPublishedSignedBeaconBlock(ForkedSignedBeaconBlock.init(blck)))
|
||||
of BeaconBlockFork.Bellatrix:
|
||||
let blck =
|
||||
try:
|
||||
SSZ.decode(body.data, bellatrix.SignedBeaconBlock)
|
||||
except SerializationError:
|
||||
return err("Unable to deserialize data")
|
||||
except CatchableError:
|
||||
return err("Unexpected deserialization error")
|
||||
ok(RestPublishedSignedBeaconBlock(ForkedSignedBeaconBlock.init(blck)))
|
||||
else:
|
||||
return err("Unsupported or invalid content media type")
|
||||
|
||||
proc decodeBody*[T](t: typedesc[T],
|
||||
body: ContentBody): Result[T, cstring] =
|
||||
if body.contentType != ApplicationJsonMediaType:
|
||||
|
@ -2329,6 +2383,33 @@ proc encodeBytes*[T: EncodeArrays](value: T,
|
|||
else:
|
||||
err("Content-Type not supported")
|
||||
|
||||
proc encodeBytes*[T: EncodeOctetTypes](
|
||||
value: T,
|
||||
contentType: string
|
||||
): RestResult[seq[byte]] =
|
||||
case contentType
|
||||
of "application/json":
|
||||
let data =
|
||||
try:
|
||||
var stream = memoryOutput()
|
||||
var writer = JsonWriter[RestJson].init(stream)
|
||||
writer.writeValue(value)
|
||||
stream.getOutput(seq[byte])
|
||||
except IOError:
|
||||
return err("Input/output error")
|
||||
except SerializationError:
|
||||
return err("Serialization error")
|
||||
ok(data)
|
||||
of "application/octet-stream":
|
||||
let data =
|
||||
try:
|
||||
SSZ.encode(value)
|
||||
except CatchableError:
|
||||
return err("Serialization error")
|
||||
ok(data)
|
||||
else:
|
||||
err("Content-Type not supported")
|
||||
|
||||
proc decodeBytes*[T: DecodeTypes](
|
||||
t: typedesc[T],
|
||||
value: openArray[byte],
|
||||
|
@ -2698,3 +2779,19 @@ proc decodeString*(t: typedesc[ValidatorFilter],
|
|||
})
|
||||
else:
|
||||
err("Incorrect validator state identifier value")
|
||||
|
||||
proc decodeString*(t: typedesc[BeaconBlockFork],
|
||||
value: string): Result[BeaconBlockFork, cstring] =
|
||||
case toLowerAscii(value)
|
||||
of "phase0": ok(BeaconBlockFork.Phase0)
|
||||
of "altair": ok(BeaconBlockFork.Altair)
|
||||
of "bellatrix": ok(BeaconBlockFork.Bellatrix)
|
||||
else: err("Unsupported or invalid beacon block fork version")
|
||||
|
||||
proc decodeString*(t: typedesc[BeaconStateFork],
|
||||
value: string): Result[BeaconStateFork, cstring] =
|
||||
case toLowerAscii(value)
|
||||
of "phase0": ok(BeaconStateFork.Phase0)
|
||||
of "altair": ok(BeaconStateFork.Altair)
|
||||
of "bellatrix": ok(BeaconStateFork.Bellatrix)
|
||||
else: err("Unsupported or invalid beacon state fork version")
|
||||
|
|
|
@ -116,6 +116,18 @@ proc publishBlock*(body: bellatrix.SignedBeaconBlock): RestPlainResponse {.
|
|||
meth: MethodPost.}
|
||||
## https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlock
|
||||
|
||||
proc publishSszBlock*(
|
||||
client: RestClientRef,
|
||||
blck: ForkySignedBeaconBlock
|
||||
): Future[RestPlainResponse] {.async.} =
|
||||
## https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlock
|
||||
let
|
||||
consensus = typeof(blck).toFork.toString()
|
||||
resp = await client.publishBlock(
|
||||
blck, restContentType = $OctetStreamMediaType,
|
||||
extraHeaders = @[("eth-consensus-version", consensus)])
|
||||
return resp
|
||||
|
||||
proc getBlockV2Plain*(block_id: BlockIdent): RestPlainResponse {.
|
||||
rest, endpoint: "/eth/v2/beacon/blocks/{block_id}",
|
||||
accept: preferSSZ,
|
||||
|
|
Loading…
Reference in New Issue