Use the ledger's context or a specific map?
Consider an author trying to maintain a library on the ledger with
template Book
with
author : Party
isin : Text
chapters : [Int]
where
signatory author
key (author, isin) : (Party, Text)
maintainer key._1
template Chapter
with
author : Party
bookIsin : Text
chapter : Int
text : Text
bookId : ContractId Book
where
signatory author
key (author, bookIsin, chapter) : (Party, Text, Int)
maintainer key._1
Now the author uses the CreateAndExercise pattern to upload the library to the ledger. But within the processing of the upload, there are two options to keep track of the association between Books and Chapters: via the ledger or via a specific Map.
template UploadLibrary
with
author : Party
books : [(Text, [Int])] -- isin, chapters
chapters : [(Text, Int, Text)] -- isin, chapter, text
where
signatory author
choice CreateViaLedger : ([ContractId Book], [ContractId Chapter])
controller author
do
bookIds <- forA books (\(isin, chapters) -> create Book with ..)
chapterIds <- forA chapters (\(bookIsin, chapter, text) -> do
-- books have been created
Some bookId <- lookupByKey @Book (author, bookIsin)
create Chapter with ..)
return (bookIds, chapterIds)
choice CreateViaMap : ([ContractId Book], [ContractId Chapter])
controller author
do
(bookMap, bookIds) <- foldlA (\(bookMap, bookIds) (isin, chapters) -> do
bookId <- create Book with ..
return (insert isin bookId bookMap, bookId::bookIds) )
(mempty, []) books
chapterIds <- forA chapters (\(bookIsin, chapter, text) -> do
let Some bookId = lookup bookIsin bookMap
create Chapter with ..)
return (bookIds, chapterIds)
What do you think is the better approach ?
- The two methods are not equivalent as the former allows one to send updates on
Chapters outside of theUploadLibrarypayload; those that might exist previously. - Is there a performance tradeoff to using the
lookupByKeyinstead of the regularMap.lookup?
Unless you can exploit the semantics of a Chapter in a ledger-specific way, e.g. by having some Chapters observable to different parties from their associated Books, I don’t see much value in having separate Chapter contracts here.
lookup in a Map is faster than looking up by contract key for small maps. The only time lookupByKey will have a performance advantage is when the Map is larger or modified sufficiently frequently; the whole Map is included with each transmitted copy of the contract that contains it, after all, and therefore you get knock-on effects like, if you build up a map one element at a time, one exercise at a time, you get n² ledger space usage. That doesn’t seem relevant at all for this example, though.