mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-02-24 04:08:32 +00:00
Add an option for graffiti customization
This commit is contained in:
parent
853bd5b799
commit
93b04bc214
@ -134,9 +134,9 @@ func enrForkIdFromState(state: BeaconState): ENRForkID =
|
||||
next_fork_version: forkVer,
|
||||
next_fork_epoch: FAR_FUTURE_EPOCH)
|
||||
|
||||
proc init*(
|
||||
T: type BeaconNode, rng: ref BrHmacDrbgContext,
|
||||
conf: BeaconNodeConf): Future[BeaconNode] {.async.} =
|
||||
proc init*(T: type BeaconNode,
|
||||
rng: ref BrHmacDrbgContext,
|
||||
conf: BeaconNodeConf): Future[BeaconNode] {.async.} =
|
||||
let
|
||||
netKeys = getPersistentNetKeys(rng[], conf)
|
||||
nickname = if conf.nodeName == "auto": shortForm(netKeys)
|
||||
@ -237,6 +237,8 @@ proc init*(
|
||||
|
||||
var res = BeaconNode(
|
||||
nickname: nickname,
|
||||
graffitiBytes: if conf.graffiti.isSome: conf.graffiti.get.GraffitiBytes
|
||||
else: defaultGraffitiBytes(),
|
||||
network: network,
|
||||
netKeys: netKeys,
|
||||
db: db,
|
||||
@ -635,11 +637,6 @@ proc currentSlot(node: BeaconNode): Slot =
|
||||
proc connectedPeersCount(node: BeaconNode): int =
|
||||
nbc_peers.value.int
|
||||
|
||||
func fromJson(n: JsonNode; argName: string; result: var Slot) =
|
||||
var i: int
|
||||
fromJson(n, argName, i)
|
||||
result = Slot(i)
|
||||
|
||||
proc installBeaconApiHandlers(rpcServer: RpcServer, node: BeaconNode) =
|
||||
rpcServer.rpc("getBeaconHead") do () -> Slot:
|
||||
return node.blockPool.head.blck.slot
|
||||
|
@ -32,6 +32,7 @@ type
|
||||
|
||||
BeaconNode* = ref object
|
||||
nickname*: string
|
||||
graffitiBytes*: GraffitiBytes
|
||||
network*: Eth2Node
|
||||
netKeys*: KeyPair
|
||||
requestManager*: RequestManager
|
||||
|
@ -4,8 +4,8 @@ import
|
||||
os, options,
|
||||
chronicles, chronicles/options as chroniclesOptions,
|
||||
confutils, confutils/defs, confutils/std/net,
|
||||
json_serialization, web3/ethtypes,
|
||||
network_metadata, spec/[crypto, keystore, digest]
|
||||
stew/byteutils, json_serialization, web3/ethtypes,
|
||||
network_metadata, spec/[crypto, keystore, digest, datatypes]
|
||||
|
||||
export
|
||||
defs, enabledLogLevel, parseCmdArg, completeCmdArg,
|
||||
@ -142,6 +142,11 @@ type
|
||||
"If you set this to 'auto', a persistent automatically generated ID will be selected for each --data-dir folder"
|
||||
name: "node-name" }: string
|
||||
|
||||
graffiti* {.
|
||||
desc: "The graffiti value that will appear in proposed blocks. " &
|
||||
"You can use a 0x-prefixed hex encoded string to specify raw bytes."
|
||||
name: "graffiti" }: Option[GraffitiBytes]
|
||||
|
||||
verifyFinalization* {.
|
||||
defaultValue: false
|
||||
desc: "Specify whether to verify finalization occurs on schedule, for testing"
|
||||
@ -361,6 +366,11 @@ type
|
||||
defaultValue: VCNoCommand }: VCStartUpCmd
|
||||
|
||||
of VCNoCommand:
|
||||
graffiti* {.
|
||||
desc: "The graffiti value that will appear in proposed blocks. " &
|
||||
"You can use a 0x-prefixed hex encoded string to specify raw bytes."
|
||||
name: "graffiti" }: Option[GraffitiBytes]
|
||||
|
||||
rpcPort* {.
|
||||
defaultValue: defaultEth2RpcPort
|
||||
desc: "HTTP port of the server to connect to for RPC"
|
||||
@ -431,6 +441,13 @@ func parseCmdArg*(T: type Eth1BlockHash, input: TaintedString): T
|
||||
func completeCmdArg*(T: type Eth1BlockHash, input: TaintedString): seq[string] =
|
||||
return @[]
|
||||
|
||||
func parseCmdArg*(T: type GraffitiBytes, input: TaintedString): T
|
||||
{.raises: [ValueError, Defect].} =
|
||||
GraffitiBytes.init(string input)
|
||||
|
||||
func completeCmdArg*(T: type GraffitiBytes, input: TaintedString): seq[string] =
|
||||
return @[]
|
||||
|
||||
func parseCmdArg*(T: type WalletName, input: TaintedString): T
|
||||
{.raises: [ValueError, Defect].} =
|
||||
if input.len == 0:
|
||||
|
@ -10,6 +10,7 @@ import
|
||||
spec/[datatypes, crypto]
|
||||
|
||||
proc fromJson*(n: JsonNode, argName: string, result: var ValidatorPubKey) =
|
||||
n.kind.expect(JString, argName)
|
||||
result = ValidatorPubKey.fromHex(n.getStr()).tryGet()
|
||||
|
||||
proc `%`*(pubkey: ValidatorPubKey): JsonNode =
|
||||
@ -26,12 +27,14 @@ proc fromJson*(n: JsonNode, argName: string, result: var BitList) =
|
||||
proc `%`*(bitlist: BitList): JsonNode = %(seq[byte](BitSeq(bitlist)))
|
||||
|
||||
proc fromJson*(n: JsonNode, argName: string, result: var ValidatorSig) =
|
||||
n.kind.expect(JString, argName)
|
||||
result = ValidatorSig.fromHex(n.getStr()).tryGet()
|
||||
|
||||
proc `%`*(value: ValidatorSig): JsonNode =
|
||||
result = newJString($value)
|
||||
|
||||
proc fromJson*(n: JsonNode, argName: string, result: var Version) =
|
||||
n.kind.expect(JString, argName)
|
||||
hexToByteArray(n.getStr(), array[4, byte](result))
|
||||
|
||||
proc `%`*(value: Version): JsonNode =
|
||||
@ -46,5 +49,12 @@ genFromJsonForIntType(Epoch)
|
||||
genFromJsonForIntType(Slot)
|
||||
genFromJsonForIntType(CommitteeIndex)
|
||||
|
||||
template `%`*(value: GraffitiBytes): JsonNode =
|
||||
%($value)
|
||||
|
||||
proc fromJson*(n: JsonNode, argName: string, value: var GraffitiBytes) =
|
||||
n.kind.expect(JString, argName)
|
||||
value = GraffitiBytes.init n.getStr()
|
||||
|
||||
proc `%`*(value: CommitteeIndex): JsonNode =
|
||||
result = newJInt(value.int)
|
||||
|
@ -25,7 +25,7 @@ import
|
||||
macros, hashes, json, strutils, tables, typetraits,
|
||||
stew/[byteutils], chronicles,
|
||||
json_serialization/types as jsonTypes,
|
||||
../ssz/types as sszTypes, ./crypto, ./digest, ./presets
|
||||
../version, ../ssz/types as sszTypes, ./crypto, ./digest, ./presets
|
||||
|
||||
export
|
||||
sszTypes, presets
|
||||
@ -257,11 +257,13 @@ type
|
||||
object_root*: Eth2Digest
|
||||
domain*: Domain
|
||||
|
||||
GraffitiBytes* = distinct array[32, byte]
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/beacon-chain.md#beaconblockbody
|
||||
BeaconBlockBody* = object
|
||||
randao_reveal*: ValidatorSig
|
||||
eth1_data*: Eth1Data
|
||||
graffiti*: Eth2Digest # TODO make that raw bytes
|
||||
graffiti*: GraffitiBytes
|
||||
|
||||
# Operations
|
||||
proposer_slashings*: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS]
|
||||
@ -273,7 +275,7 @@ type
|
||||
TrustedBeaconBlockBody* = object
|
||||
randao_reveal*: TrustedSig
|
||||
eth1_data*: Eth1Data
|
||||
graffiti*: Eth2Digest # TODO make that raw bytes
|
||||
graffiti*: GraffitiBytes
|
||||
|
||||
# Operations
|
||||
proposer_slashings*: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS]
|
||||
@ -676,6 +678,41 @@ import json_serialization
|
||||
export json_serialization
|
||||
export writeValue, readValue
|
||||
|
||||
func `$`*(value: GraffitiBytes): string =
|
||||
strip(string.fromBytes(distinctBase value), chars = Whitespace + {'\0'})
|
||||
|
||||
func init*(T: type GraffitiBytes, input: string): GraffitiBytes
|
||||
{.raises: [ValueError, Defect].} =
|
||||
if input.len > 2 and input[0] == '0' and input[1] == 'x':
|
||||
if input.len > sizeof(GraffitiBytes) * 2 + 2:
|
||||
raise newException(ValueError, "The graffiti bytes should be less than 32")
|
||||
elif input.len mod 2 != 0:
|
||||
raise newException(ValueError, "The graffiti hex string should have an even length")
|
||||
|
||||
hexToByteArray(string input, distinctBase(result))
|
||||
else:
|
||||
if input.len > 32:
|
||||
raise newException(ValueError, "The graffiti value should be 32 characters or less")
|
||||
distinctBase(result)[0 ..< input.len] = toBytes(input)
|
||||
|
||||
func defaultGraffitiBytes*(): GraffitiBytes =
|
||||
let graffityBytes = toBytes("Nimbus " & fullVersionStr)
|
||||
distinctBase(result)[0 ..< graffityBytes.len] = graffityBytes
|
||||
|
||||
proc writeValue*(w: var JsonWriter, value: GraffitiBytes)
|
||||
{.raises: [IOError, Defect].} =
|
||||
w.writeValue $value
|
||||
|
||||
template `==`*(lhs, rhs: GraffitiBytes): bool =
|
||||
distinctBase(lhs) == distinctBase(rhs)
|
||||
|
||||
proc readValue*(r: var JsonReader, T: type GraffitiBytes): T
|
||||
{.raises: [IOError, SerializationError, Defect].} =
|
||||
try:
|
||||
init(GraffitiBytes, r.readValue(string))
|
||||
except ValueError as err:
|
||||
r.raiseUnexpectedValue err.msg
|
||||
|
||||
static:
|
||||
# Sanity checks - these types should be trivial enough to copy with memcpy
|
||||
doAssert supportsCopyMem(Validator)
|
||||
|
@ -10,7 +10,7 @@ import
|
||||
# calls that return a bool are actually without a return type in the main REST API
|
||||
# spec but nim-json-rpc requires that all RPC calls have a return type.
|
||||
|
||||
proc get_v1_validator_block(slot: Slot, graffiti: Eth2Digest, randao_reveal: ValidatorSig): BeaconBlock
|
||||
proc get_v1_validator_block(slot: Slot, graffiti: GraffitiBytes, randao_reveal: ValidatorSig): BeaconBlock
|
||||
|
||||
proc post_v1_validator_block(body: SignedBeaconBlock): bool
|
||||
|
||||
|
@ -273,7 +273,7 @@ proc makeBeaconBlock*(
|
||||
parent_root: Eth2Digest,
|
||||
randao_reveal: ValidatorSig,
|
||||
eth1_data: Eth1Data,
|
||||
graffiti: Eth2Digest,
|
||||
graffiti: GraffitiBytes,
|
||||
attestations: seq[Attestation],
|
||||
deposits: seq[Deposit],
|
||||
rollback: RollbackHashedProc,
|
||||
|
@ -41,6 +41,11 @@ func fromSszBytes*(T: type Eth2Digest, data: openarray[byte]): T {.raisesssz.} =
|
||||
raiseIncorrectSize T
|
||||
copyMem(result.data.addr, unsafeAddr data[0], sizeof(result.data))
|
||||
|
||||
func fromSszBytes*(T: type GraffitiBytes, data: openarray[byte]): T {.raisesssz.} =
|
||||
if data.len != sizeof(result):
|
||||
raiseIncorrectSize T
|
||||
copyMem(result.addr, unsafeAddr data[0], sizeof(result))
|
||||
|
||||
template fromSszBytes*(T: type Slot, bytes: openarray[byte]): Slot =
|
||||
Slot fromSszBytes(uint64, bytes)
|
||||
|
||||
|
@ -15,5 +15,5 @@ template toSszType*(x: auto): auto =
|
||||
when x is Slot|Epoch|ValidatorIndex: uint64(x)
|
||||
elif x is Eth2Digest: x.data
|
||||
elif x is BlsCurveType: toRaw(x)
|
||||
elif x is ForkDigest|Version: distinctBase(x)
|
||||
elif x is ForkDigest|Version|GraffitiBytes: distinctBase(x)
|
||||
else: x
|
||||
|
@ -300,10 +300,9 @@ proc installValidatorApiHandlers*(rpcServer: RpcServer, node: BeaconNode) =
|
||||
return state
|
||||
|
||||
rpcServer.rpc("get_v1_validator_block") do (
|
||||
slot: Slot, graffiti: Eth2Digest, randao_reveal: ValidatorSig) -> BeaconBlock:
|
||||
slot: Slot, graffiti: GraffitiBytes, randao_reveal: ValidatorSig) -> BeaconBlock:
|
||||
debug "get_v1_validator_block", slot = slot
|
||||
let head = node.doChecksAndGetCurrentHead(slot)
|
||||
|
||||
let proposer = node.blockPool.getProposer(head, slot)
|
||||
if proposer.isNone():
|
||||
raise newException(CatchableError, "could not retrieve block for slot: " & $slot)
|
||||
|
@ -17,7 +17,7 @@ import
|
||||
|
||||
# Local modules
|
||||
spec/[datatypes, digest, crypto, helpers, network],
|
||||
conf, time,
|
||||
conf, time, version,
|
||||
eth2_network, eth2_discovery, validator_pool, beacon_node_types,
|
||||
nimbus_binary_common,
|
||||
version, ssz/merkleization,
|
||||
@ -36,6 +36,7 @@ createRpcSigs(RpcClient, sourceDir / "spec" / "eth2_apis" / "beacon_callsigs.nim
|
||||
type
|
||||
ValidatorClient = ref object
|
||||
config: ValidatorClientConf
|
||||
graffitiBytes: GraffitiBytes
|
||||
client: RpcHttpClient
|
||||
beaconClock: BeaconClock
|
||||
attachedValidators: ValidatorPool
|
||||
@ -136,10 +137,8 @@ proc onSlotStart(vc: ValidatorClient, lastSlot, scheduledSlot: Slot) {.gcsafe, a
|
||||
let randao_reveal = validator.genRandaoReveal(
|
||||
vc.fork, vc.beaconGenesis.genesis_validators_root, slot)
|
||||
|
||||
var graffiti: Eth2Digest
|
||||
graffiti.data[0..<5] = toBytes("quack")
|
||||
var newBlock = SignedBeaconBlock(
|
||||
message: await vc.client.get_v1_validator_block(slot, graffiti, randao_reveal)
|
||||
message: await vc.client.get_v1_validator_block(slot, vc.graffitiBytes, randao_reveal)
|
||||
)
|
||||
|
||||
let blockRoot = hash_tree_root(newBlock.message)
|
||||
@ -212,8 +211,9 @@ programMain:
|
||||
|
||||
var vc = ValidatorClient(
|
||||
config: config,
|
||||
client: newRpcHttpClient()
|
||||
)
|
||||
client: newRpcHttpClient(),
|
||||
graffitiBytes: if config.graffiti.isSome: config.graffiti.get.GraffitiBytes
|
||||
else: defaultGraffitiBytes())
|
||||
|
||||
# load all the validators from the data dir into memory
|
||||
for curr in vc.config.validatorKeys:
|
||||
|
@ -10,7 +10,7 @@ import
|
||||
os, tables, strutils,
|
||||
|
||||
# Nimble packages
|
||||
stew/[byteutils, objects], stew/shims/macros,
|
||||
stew/[objects], stew/shims/macros,
|
||||
chronos, metrics, json_rpc/[rpcserver, jsonmarshal],
|
||||
chronicles,
|
||||
json_serialization/std/[options, sets, net], serialization/errors,
|
||||
@ -160,7 +160,7 @@ type
|
||||
proc makeBeaconBlockForHeadAndSlot*(node: BeaconNode,
|
||||
val_info: ValidatorInfoForMakeBeaconBlock,
|
||||
validator_index: ValidatorIndex,
|
||||
graffiti: Eth2Digest,
|
||||
graffiti: GraffitiBytes,
|
||||
head: BlockRef,
|
||||
slot: Slot):
|
||||
tuple[message: Option[BeaconBlock], fork: Fork, genesis_validators_root: Eth2Digest] =
|
||||
@ -271,11 +271,8 @@ proc proposeBlock(node: BeaconNode,
|
||||
cat = "fastforward"
|
||||
return head
|
||||
|
||||
var graffiti: Eth2Digest
|
||||
graffiti.data[0..<5] = toBytes("quack")
|
||||
let valInfo = ValidatorInfoForMakeBeaconBlock(kind: viValidator, validator: validator)
|
||||
let beaconBlockTuple = makeBeaconBlockForHeadAndSlot(node, valInfo, validator_index, graffiti, head, slot)
|
||||
|
||||
let beaconBlockTuple = makeBeaconBlockForHeadAndSlot(node, valInfo, validator_index, node.graffitiBytes, head, slot)
|
||||
if not beaconBlockTuple.message.isSome():
|
||||
return head # already logged elsewhere!
|
||||
var
|
||||
|
@ -37,3 +37,4 @@ func shortNimBanner*(): string =
|
||||
tmp[0] & " (" & gitHash & ")"
|
||||
else:
|
||||
tmp[0]
|
||||
|
||||
|
@ -114,7 +114,7 @@ cli do(slots = SLOTS_PER_EPOCH * 6,
|
||||
head.root,
|
||||
privKey.genRandaoReveal(state.fork, state.genesis_validators_root, slot),
|
||||
eth1data,
|
||||
Eth2Digest(),
|
||||
default(GraffitiBytes),
|
||||
attPool.getAttestationsForBlock(state),
|
||||
@[],
|
||||
noRollback,
|
||||
|
@ -204,7 +204,7 @@ suiteReport "Attestation pool processing" & preset():
|
||||
|
||||
let
|
||||
b11 = makeTestBlock(state.data, blockPool[].tail.root, cache,
|
||||
graffiti = Eth2Digest(data: [1'u8, 0, 0, 0 ,0 ,0 ,0 ,0 ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
||||
graffiti = GraffitiBytes [1'u8, 0, 0, 0 ,0 ,0 ,0 ,0 ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
)
|
||||
b11Root = hash_tree_root(b11.message)
|
||||
b11Add = blockpool[].addRawBlock(b11Root, b11) do (validBlock: BlockRef):
|
||||
|
@ -91,7 +91,7 @@ proc addTestBlock*(
|
||||
eth1_data = Eth1Data(),
|
||||
attestations = newSeq[Attestation](),
|
||||
deposits = newSeq[Deposit](),
|
||||
graffiti = Eth2Digest(),
|
||||
graffiti = default(GraffitiBytes),
|
||||
flags: set[UpdateFlag] = {}): SignedBeaconBlock =
|
||||
# Create and add a block to state - state will advance by one slot!
|
||||
advance_slot(state, flags, cache)
|
||||
@ -140,7 +140,7 @@ proc makeTestBlock*(
|
||||
eth1_data = Eth1Data(),
|
||||
attestations = newSeq[Attestation](),
|
||||
deposits = newSeq[Deposit](),
|
||||
graffiti = Eth2Digest(),
|
||||
graffiti = default(GraffitiBytes),
|
||||
flags: set[UpdateFlag] = {}): SignedBeaconBlock =
|
||||
# Create a block for `state.slot + 1` - like a block proposer would do!
|
||||
# It's a bit awkward - in order to produce a block for N+1, we need to
|
||||
|
Loading…
x
Reference in New Issue
Block a user