Fluffy state portal rpc validation (#2719)
* Validate content key in portal_stateLocalContent. * Add additional validation to stateStore rpc method.
This commit is contained in:
parent
5edb0b320f
commit
b13f06fcfb
|
@ -45,7 +45,6 @@ proc validateTrieProof*(
|
|||
if proof.len() == 0:
|
||||
return err("proof is empty")
|
||||
|
||||
# TODO: Remove this once the hive tests support passing in state roots from the history network
|
||||
if expectedRootHash.isSome():
|
||||
if not proof[0].hashEquals(expectedRootHash.get()):
|
||||
return err("hash of proof root node doesn't match the expected root hash")
|
||||
|
|
|
@ -1590,12 +1590,15 @@ proc storeContent*(
|
|||
contentKey: ContentKeyByteList,
|
||||
contentId: ContentId,
|
||||
content: seq[byte],
|
||||
) =
|
||||
): bool {.discardable.} =
|
||||
# Always re-check that the key is still in the node range to make sure only
|
||||
# content in range is stored.
|
||||
if p.inRange(contentId):
|
||||
doAssert(p.dbPut != nil)
|
||||
p.dbPut(contentKey, contentId, content)
|
||||
true
|
||||
else:
|
||||
false
|
||||
|
||||
proc seedTable*(p: PortalProtocol) =
|
||||
## Seed the table with specifically provided Portal bootstrap nodes. These are
|
||||
|
|
|
@ -115,13 +115,10 @@ proc installPortalBeaconApiHandlers*(rpcServer: RpcServer, p: PortalProtocol) =
|
|||
let
|
||||
key = ContentKeyByteList.init(hexToSeqByte(contentKey))
|
||||
contentValueBytes = hexToSeqByte(contentValue)
|
||||
contentId = p.toContentId(key)
|
||||
contentId = p.toContentId(key).valueOr:
|
||||
raise invalidKeyErr()
|
||||
|
||||
if contentId.isSome():
|
||||
p.storeContent(key, contentId.get(), contentValueBytes)
|
||||
return true
|
||||
else:
|
||||
raise invalidKeyErr()
|
||||
p.storeContent(key, contentId, contentValueBytes)
|
||||
|
||||
rpcServer.rpc("portal_beaconLocalContent") do(contentKey: string) -> string:
|
||||
let
|
||||
|
|
|
@ -115,13 +115,10 @@ proc installPortalHistoryApiHandlers*(rpcServer: RpcServer, p: PortalProtocol) =
|
|||
let
|
||||
key = ContentKeyByteList.init(hexToSeqByte(contentKey))
|
||||
contentValueBytes = hexToSeqByte(contentValue)
|
||||
contentId = p.toContentId(key)
|
||||
contentId = p.toContentId(key).valueOr:
|
||||
raise invalidKeyErr()
|
||||
|
||||
if contentId.isSome():
|
||||
p.storeContent(key, contentId.get(), contentValueBytes)
|
||||
return true
|
||||
else:
|
||||
raise invalidKeyErr()
|
||||
p.storeContent(key, contentId, contentValueBytes)
|
||||
|
||||
rpcServer.rpc("portal_historyLocalContent") do(contentKey: string) -> string:
|
||||
let
|
||||
|
|
|
@ -13,7 +13,7 @@ import
|
|||
json_serialization/std/tables,
|
||||
stew/byteutils,
|
||||
../network/wire/portal_protocol,
|
||||
../network/state/state_content,
|
||||
../network/state/[state_content, state_validation],
|
||||
./rpc_types
|
||||
|
||||
{.warning[UnusedImport]: off.}
|
||||
|
@ -114,41 +114,47 @@ proc installPortalStateApiHandlers*(rpcServer: RpcServer, p: PortalProtocol) =
|
|||
contentKey: string, contentValue: string
|
||||
) -> bool:
|
||||
let
|
||||
key = ContentKeyByteList.init(hexToSeqByte(contentKey))
|
||||
contentValueBytes = hexToSeqByte(contentValue)
|
||||
decodedKey = ContentKey.decode(key).valueOr:
|
||||
keyBytes = ContentKeyByteList.init(hexToSeqByte(contentKey))
|
||||
key = ContentKey.decode(keyBytes).valueOr:
|
||||
raise invalidKeyErr()
|
||||
contentId = p.toContentId(keyBytes).valueOr:
|
||||
raise invalidKeyErr()
|
||||
|
||||
contentBytes = hexToSeqByte(contentValue)
|
||||
valueToStore =
|
||||
case decodedKey.contentType
|
||||
case key.contentType
|
||||
of unused:
|
||||
raise invalidKeyErr()
|
||||
of accountTrieNode:
|
||||
let offerValue = AccountTrieNodeOffer.decode(contentValueBytes).valueOr:
|
||||
let offer = AccountTrieNodeOffer.decode(contentBytes).valueOr:
|
||||
raise invalidValueErr
|
||||
offerValue.toRetrievalValue.encode()
|
||||
validateOffer(Opt.none(Hash32), key.accountTrieNodeKey, offer).isOkOr:
|
||||
raise invalidValueErr
|
||||
offer.toRetrievalValue.encode()
|
||||
of contractTrieNode:
|
||||
let offerValue = ContractTrieNodeOffer.decode(contentValueBytes).valueOr:
|
||||
let offer = ContractTrieNodeOffer.decode(contentBytes).valueOr:
|
||||
raise invalidValueErr
|
||||
offerValue.toRetrievalValue.encode()
|
||||
validateOffer(Opt.none(Hash32), key.contractTrieNodeKey, offer).isOkOr:
|
||||
raise invalidValueErr
|
||||
offer.toRetrievalValue.encode()
|
||||
of contractCode:
|
||||
let offerValue = ContractCodeOffer.decode(contentValueBytes).valueOr:
|
||||
let offer = ContractCodeOffer.decode(contentBytes).valueOr:
|
||||
raise invalidValueErr
|
||||
offerValue.toRetrievalValue.encode()
|
||||
validateOffer(Opt.none(Hash32), key.contractCodeKey, offer).isOkOr:
|
||||
raise invalidValueErr
|
||||
offer.toRetrievalValue.encode()
|
||||
|
||||
let contentId = p.toContentId(key)
|
||||
if contentId.isSome():
|
||||
p.storeContent(key, contentId.get(), valueToStore)
|
||||
return true
|
||||
else:
|
||||
raise invalidKeyErr()
|
||||
p.storeContent(keyBytes, contentId, valueToStore)
|
||||
|
||||
rpcServer.rpc("portal_stateLocalContent") do(contentKey: string) -> string:
|
||||
let
|
||||
key = ContentKeyByteList.init(hexToSeqByte(contentKey))
|
||||
contentId = p.toContentId(key).valueOr:
|
||||
keyBytes = ContentKeyByteList.init(hexToSeqByte(contentKey))
|
||||
key = ContentKey.decode(keyBytes).valueOr:
|
||||
raise invalidKeyErr()
|
||||
contentId = p.toContentId(keyBytes).valueOr:
|
||||
raise invalidKeyErr()
|
||||
|
||||
contentResult = p.dbGet(key, contentId).valueOr:
|
||||
contentResult = p.dbGet(keyBytes, contentId).valueOr:
|
||||
raise contentNotFoundErr()
|
||||
|
||||
return contentResult.to0xHex()
|
||||
|
|
Loading…
Reference in New Issue