mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-20 01:07:18 +03:00
[engine] kill Daml withAuthority / LF WITH_AUTHORITY (#16548)
This commit is contained in:
parent
e1a96bc543
commit
ac68bdf416
@ -301,9 +301,6 @@ data BuiltinExpr
|
|||||||
| BEFoldr -- :: ∀a b. (a -> b -> b) -> b -> List a -> b
|
| BEFoldr -- :: ∀a b. (a -> b -> b) -> b -> List a -> b
|
||||||
| BEEqualList -- :: ∀a. (a -> a -> Bool) -> List a -> List a -> Bool
|
| BEEqualList -- :: ∀a. (a -> a -> Bool) -> List a -> List a -> Bool
|
||||||
|
|
||||||
-- Authority operations
|
|
||||||
| BEWithAuthority -- :: ∀ a. List Party -> Update a -> Update a
|
|
||||||
|
|
||||||
-- Map operations
|
-- Map operations
|
||||||
| BETextMapEmpty -- :: ∀ a. TextMap a
|
| BETextMapEmpty -- :: ∀ a. TextMap a
|
||||||
| BETextMapInsert -- :: ∀ a. Text -> a -> TextMap a -> TextMap a
|
| BETextMapInsert -- :: ∀ a. Text -> a -> TextMap a -> TextMap a
|
||||||
|
@ -267,7 +267,6 @@ instance Pretty BuiltinExpr where
|
|||||||
BEExpInt64 -> "EXP_INT64"
|
BEExpInt64 -> "EXP_INT64"
|
||||||
BEFoldl -> "FOLDL"
|
BEFoldl -> "FOLDL"
|
||||||
BEFoldr -> "FOLDR"
|
BEFoldr -> "FOLDR"
|
||||||
BEWithAuthority -> "WITH_AUTHORITY"
|
|
||||||
BETextMapEmpty -> "TEXTMAP_EMPTY"
|
BETextMapEmpty -> "TEXTMAP_EMPTY"
|
||||||
BETextMapInsert -> "TEXTMAP_INSERT"
|
BETextMapInsert -> "TEXTMAP_INSERT"
|
||||||
BETextMapLookup -> "TEXTMAP_LOOKUP"
|
BETextMapLookup -> "TEXTMAP_LOOKUP"
|
||||||
|
@ -476,7 +476,6 @@ decodeBuiltinFunction = \case
|
|||||||
|
|
||||||
LF1.BuiltinFunctionFOLDL -> pure BEFoldl
|
LF1.BuiltinFunctionFOLDL -> pure BEFoldl
|
||||||
LF1.BuiltinFunctionFOLDR -> pure BEFoldr
|
LF1.BuiltinFunctionFOLDR -> pure BEFoldr
|
||||||
LF1.BuiltinFunctionWITH_AUTHORITY -> pure BEWithAuthority
|
|
||||||
LF1.BuiltinFunctionEQUAL_LIST -> pure BEEqualList
|
LF1.BuiltinFunctionEQUAL_LIST -> pure BEEqualList
|
||||||
LF1.BuiltinFunctionAPPEND_TEXT -> pure BEAppendText
|
LF1.BuiltinFunctionAPPEND_TEXT -> pure BEAppendText
|
||||||
|
|
||||||
|
@ -516,7 +516,6 @@ encodeBuiltinExpr = \case
|
|||||||
|
|
||||||
BEFoldl -> builtin P.BuiltinFunctionFOLDL
|
BEFoldl -> builtin P.BuiltinFunctionFOLDL
|
||||||
BEFoldr -> builtin P.BuiltinFunctionFOLDR
|
BEFoldr -> builtin P.BuiltinFunctionFOLDR
|
||||||
BEWithAuthority -> builtin P.BuiltinFunctionWITH_AUTHORITY
|
|
||||||
BEEqualList -> builtin P.BuiltinFunctionEQUAL_LIST
|
BEEqualList -> builtin P.BuiltinFunctionEQUAL_LIST
|
||||||
BEExplodeText -> builtin P.BuiltinFunctionEXPLODE_TEXT
|
BEExplodeText -> builtin P.BuiltinFunctionEXPLODE_TEXT
|
||||||
BEAppendText -> builtin P.BuiltinFunctionAPPEND_TEXT
|
BEAppendText -> builtin P.BuiltinFunctionAPPEND_TEXT
|
||||||
|
@ -137,7 +137,6 @@ safetyStep = \case
|
|||||||
BEExpInt64 -> Safe 1
|
BEExpInt64 -> Safe 1
|
||||||
BEFoldl -> Safe 2
|
BEFoldl -> Safe 2
|
||||||
BEFoldr -> Safe 2
|
BEFoldr -> Safe 2
|
||||||
BEWithAuthority -> Safe 2 -- not reachable; so "undefined" would suffice
|
|
||||||
BETextMapEmpty -> Safe 0
|
BETextMapEmpty -> Safe 0
|
||||||
BETextMapInsert -> Safe 3
|
BETextMapInsert -> Safe 3
|
||||||
BETextMapLookup -> Safe 2
|
BETextMapLookup -> Safe 2
|
||||||
|
@ -278,12 +278,6 @@ typeOfBuiltin = \case
|
|||||||
BEFoldr -> pure $ TForall (alpha, KStar) $ TForall (beta, KStar) $
|
BEFoldr -> pure $ TForall (alpha, KStar) $ TForall (beta, KStar) $
|
||||||
(tAlpha :-> tBeta :-> tBeta) :-> tBeta :-> TList tAlpha :-> tBeta
|
(tAlpha :-> tBeta :-> tBeta) :-> tBeta :-> TList tAlpha :-> tBeta
|
||||||
|
|
||||||
BEWithAuthority ->
|
|
||||||
pure $ TForall (alpha, KStar) $
|
|
||||||
TList TParty :->
|
|
||||||
TUpdate tAlpha :->
|
|
||||||
TUpdate tAlpha
|
|
||||||
|
|
||||||
BETextMapEmpty -> pure $ TForall (alpha, KStar) $ TTextMap tAlpha
|
BETextMapEmpty -> pure $ TForall (alpha, KStar) $ TTextMap tAlpha
|
||||||
BETextMapInsert -> pure $ TForall (alpha, KStar) $ TText :-> tAlpha :-> TTextMap tAlpha :-> TTextMap tAlpha
|
BETextMapInsert -> pure $ TForall (alpha, KStar) $ TText :-> tAlpha :-> TTextMap tAlpha :-> TTextMap tAlpha
|
||||||
BETextMapLookup -> pure $ TForall (alpha, KStar) $ TText :-> TTextMap tAlpha :-> TOptional tAlpha
|
BETextMapLookup -> pure $ TForall (alpha, KStar) $ TText :-> TTextMap tAlpha :-> TOptional tAlpha
|
||||||
|
@ -88,10 +88,6 @@ convertPrim _ "BEFoldl" ((b1 :-> a1 :-> b2) :-> b3 :-> TList a2 :-> b4) | a1 ==
|
|||||||
convertPrim _ "BEFoldr" ((a1 :-> b1 :-> b2) :-> b3 :-> TList a2 :-> b4) | a1 == a2, b1 == b2, b2 == b3, b3 == b4 =
|
convertPrim _ "BEFoldr" ((a1 :-> b1 :-> b2) :-> b3 :-> TList a2 :-> b4) | a1 == a2, b1 == b2, b2 == b3, b3 == b4 =
|
||||||
pure $ EBuiltin BEFoldr `ETyApp` a1 `ETyApp` b1
|
pure $ EBuiltin BEFoldr `ETyApp` a1 `ETyApp` b1
|
||||||
|
|
||||||
-- Authority operations
|
|
||||||
convertPrim _ "BEWithAuthority" (TList TParty :-> TUpdate a1 :-> TUpdate a2) | a1 == a2 =
|
|
||||||
pure $ EBuiltin BEWithAuthority `ETyApp` a1
|
|
||||||
|
|
||||||
-- Error
|
-- Error
|
||||||
convertPrim _ "BEError" (TText :-> t2) =
|
convertPrim _ "BEError" (TText :-> t2) =
|
||||||
pure $ ETyApp (EBuiltin BEError) t2
|
pure $ ETyApp (EBuiltin BEError) t2
|
||||||
|
@ -48,10 +48,6 @@ module DA.Internal.LF
|
|||||||
, AnyException
|
, AnyException
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DAML_WITH_AUTHORITY
|
|
||||||
, withAuthorityOf
|
|
||||||
#endif
|
|
||||||
|
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import GHC.Stack.Types (HasCallStack)
|
import GHC.Stack.Types (HasCallStack)
|
||||||
@ -276,11 +272,3 @@ instance Ord TypeRep where
|
|||||||
data AnyException = AnyException Opaque
|
data AnyException = AnyException Opaque
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DAML_WITH_AUTHORITY
|
|
||||||
|
|
||||||
-- | Authority operations.
|
|
||||||
withAuthorityOf : [Party] -> Update a -> Update a
|
|
||||||
withAuthorityOf = primitive @"BEWithAuthority"
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -29,3 +29,6 @@ template ProposeConsortiumAuthority
|
|||||||
withAuthorityOf accepted $ do
|
withAuthorityOf accepted $ do
|
||||||
withAuthorityOf [consortiumParty] $ do
|
withAuthorityOf [consortiumParty] $ do
|
||||||
create HasConsortiumAutority with consortiumParty
|
create HasConsortiumAutority with consortiumParty
|
||||||
|
|
||||||
|
withAuthorityOf : [Party] -> Update a -> Update a
|
||||||
|
withAuthorityOf _ u = u -- TODO #15882 -- require rework
|
||||||
|
@ -571,9 +571,7 @@ enum BuiltinFunction {
|
|||||||
|
|
||||||
TYPE_REP_TYCON_NAME = 148; // *Available in versions >= 1.dev*
|
TYPE_REP_TYCON_NAME = 148; // *Available in versions >= 1.dev*
|
||||||
|
|
||||||
WITH_AUTHORITY = 149; // *Available in versions >= 1.dev*
|
// Next id is 149.
|
||||||
|
|
||||||
// Next id is 150.
|
|
||||||
|
|
||||||
// EXPERIMENTAL TEXT PRIMITIVES -- these do not yet have stable numbers.
|
// EXPERIMENTAL TEXT PRIMITIVES -- these do not yet have stable numbers.
|
||||||
TEXT_TO_UPPER = 9901; // *Available in versions >= 1.dev*
|
TEXT_TO_UPPER = 9901; // *Available in versions >= 1.dev*
|
||||||
|
@ -2099,7 +2099,6 @@ private[archive] object DecodeV1 {
|
|||||||
BuiltinFunctionInfo(NUMERIC_TO_INT64, BNumericToInt64, minVersion = numeric),
|
BuiltinFunctionInfo(NUMERIC_TO_INT64, BNumericToInt64, minVersion = numeric),
|
||||||
BuiltinFunctionInfo(FOLDL, BFoldl),
|
BuiltinFunctionInfo(FOLDL, BFoldl),
|
||||||
BuiltinFunctionInfo(FOLDR, BFoldr),
|
BuiltinFunctionInfo(FOLDR, BFoldr),
|
||||||
BuiltinFunctionInfo(WITH_AUTHORITY, BWithAuthority),
|
|
||||||
BuiltinFunctionInfo(TEXTMAP_EMPTY, BTextMapEmpty),
|
BuiltinFunctionInfo(TEXTMAP_EMPTY, BTextMapEmpty),
|
||||||
BuiltinFunctionInfo(TEXTMAP_INSERT, BTextMapInsert),
|
BuiltinFunctionInfo(TEXTMAP_INSERT, BTextMapInsert),
|
||||||
BuiltinFunctionInfo(TEXTMAP_LOOKUP, BTextMapLookup),
|
BuiltinFunctionInfo(TEXTMAP_LOOKUP, BTextMapLookup),
|
||||||
|
@ -2509,8 +2509,8 @@ class EngineTest
|
|||||||
case Right((_, _)) =>
|
case Right((_, _)) =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
"authority required; not granted" in {
|
"authority required; not granted" in { // TODO #15882 -- rework required
|
||||||
inside(run(mkCommand(party1 = alice, party2 = bob), grantNeedAuthority = false)) {
|
inside(run(mkCommand(party1 = alice, party2 = bob), grantNeedAuthority = false)) {
|
||||||
case Left(
|
case Left(
|
||||||
Interpretation(
|
Interpretation(
|
||||||
@ -2523,11 +2523,12 @@ class EngineTest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"authority required; granted" in {
|
"authority required; granted" in { // TODO #15882 -- rework required
|
||||||
inside(run(mkCommand(party1 = alice, party2 = bob), grantNeedAuthority = true)) {
|
inside(run(mkCommand(party1 = alice, party2 = bob), grantNeedAuthority = true)) {
|
||||||
case Right((_, _)) =>
|
case Right((_, _)) =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,9 +472,6 @@ private[lf] final class PhaseOne(
|
|||||||
case BFoldr => SBFoldr
|
case BFoldr => SBFoldr
|
||||||
case BEqualList => SBEqualList
|
case BEqualList => SBEqualList
|
||||||
|
|
||||||
// Authority functions
|
|
||||||
case BWithAuthority => SBWithAuthority
|
|
||||||
|
|
||||||
// Errors
|
// Errors
|
||||||
case BError => SBUserError
|
case BError => SBUserError
|
||||||
|
|
||||||
|
@ -1,559 +0,0 @@
|
|||||||
// Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package com.daml.lf
|
|
||||||
package speedy
|
|
||||||
|
|
||||||
import com.daml.lf.data.FrontStack
|
|
||||||
import com.daml.lf.data.ImmArray
|
|
||||||
import com.daml.lf.data.Ref.Party
|
|
||||||
import com.daml.lf.interpretation.Error.FailedAuthorization
|
|
||||||
import com.daml.lf.ledger.FailedAuthorization.CreateMissingAuthorization
|
|
||||||
import com.daml.lf.speedy.SError.SError
|
|
||||||
import com.daml.lf.speedy.SExpr.SEApp
|
|
||||||
import com.daml.lf.speedy.SValue.{SList, SParty}
|
|
||||||
import com.daml.lf.testing.parser.Implicits._
|
|
||||||
import com.daml.lf.transaction.Node
|
|
||||||
import com.daml.lf.transaction.NodeId
|
|
||||||
import com.daml.lf.transaction.SubmittedTransaction
|
|
||||||
import com.daml.lf.value.Value.{ValueRecord, ValueParty}
|
|
||||||
|
|
||||||
import org.scalatest.Inside
|
|
||||||
import org.scalatest.freespec.AnyFreeSpec
|
|
||||||
import org.scalatest.matchers.should.Matchers._
|
|
||||||
|
|
||||||
class WithAuthorityTest extends AnyFreeSpec with Inside {
|
|
||||||
|
|
||||||
val a = Party.assertFromString("Alice")
|
|
||||||
val b = Party.assertFromString("Bob")
|
|
||||||
val c = Party.assertFromString("Charlie")
|
|
||||||
|
|
||||||
import WithAuthorityTest._
|
|
||||||
import SpeedyTestLib.AuthRequest
|
|
||||||
|
|
||||||
"Single" - {
|
|
||||||
|
|
||||||
"single (auth changed): A->{B}->A [FAIL]" in {
|
|
||||||
inside(makeSingle(committers = Set(a), required = Set(b), signed = a)) { case Left(err) =>
|
|
||||||
inside(err) { case SError.SErrorDamlException(FailedAuthorization(_, why)) =>
|
|
||||||
inside(why) { case cma: CreateMissingAuthorization =>
|
|
||||||
cma.authorizingParties shouldBe Set(b)
|
|
||||||
cma.requiredParties shouldBe Set(a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"single (auth changed): A->{B}->B [OK]" in {
|
|
||||||
inside(makeSingle(committers = Set(a), required = Set(b), signed = b)) {
|
|
||||||
case Right((tx, ars)) =>
|
|
||||||
val shape = shapeOfTransaction(tx)
|
|
||||||
val expected = List(Authority(Set(b), List(Create(b))))
|
|
||||||
shape shouldBe expected
|
|
||||||
ars shouldBe List(AuthRequest(holding = Set(a), requesting = Set(b)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"single (auth restricted/extended) {A,B}->{B,C}->A [FAIL]" in {
|
|
||||||
inside(makeSingle(committers = Set(a, b), required = Set(b, c), signed = a)) {
|
|
||||||
case Left(err) =>
|
|
||||||
inside(err) { case SError.SErrorDamlException(FailedAuthorization(_, why)) =>
|
|
||||||
inside(why) { case cma: CreateMissingAuthorization =>
|
|
||||||
cma.authorizingParties shouldBe Set(b, c)
|
|
||||||
cma.requiredParties shouldBe Set(a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"single (auth restricted/extended) {A,B}->{B,C}->B [OK]" in {
|
|
||||||
inside(makeSingle(committers = Set(a, b), required = Set(b, c), signed = b)) {
|
|
||||||
case Right((tx, ars)) =>
|
|
||||||
val shape = shapeOfTransaction(tx)
|
|
||||||
val expected = List(Authority(Set(b, c), List(Create(b))))
|
|
||||||
shape shouldBe expected
|
|
||||||
ars shouldBe List(AuthRequest(holding = Set(a, b), requesting = Set(c)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"single (auth restricted/extended) {A,B}->{B,C}->C [OK]" in {
|
|
||||||
inside(makeSingle(committers = Set(a, b), required = Set(b, c), signed = c)) {
|
|
||||||
case Right((tx, ars)) =>
|
|
||||||
val shape = shapeOfTransaction(tx)
|
|
||||||
val expected = List(Authority(Set(b, c), List(Create(c))))
|
|
||||||
shape shouldBe expected
|
|
||||||
ars shouldBe List(AuthRequest(holding = Set(a, b), requesting = Set(c)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"single (auth unchanged) A->{A}->A [OK; no auth-node]" in {
|
|
||||||
inside(makeSingle(committers = Set(a), required = Set(a), signed = a)) {
|
|
||||||
case Right((tx, ars)) =>
|
|
||||||
val shape = shapeOfTransaction(tx)
|
|
||||||
val expected = List(Create(a))
|
|
||||||
shape shouldBe expected
|
|
||||||
ars shouldBe List()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"single (auth restricted) {A,B}->{B}->B [OK; no auth-node]" in {
|
|
||||||
inside(makeSingle(committers = Set(a, b), required = Set(b), signed = b)) {
|
|
||||||
case Right((tx, ars)) =>
|
|
||||||
val shape = shapeOfTransaction(tx)
|
|
||||||
val expected = List(Create(b))
|
|
||||||
shape shouldBe expected
|
|
||||||
ars shouldBe List()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"single (auth restricted) {A,B}->{B}->A [FAIL]" in {
|
|
||||||
inside(makeSingle(committers = Set(a, b), required = Set(b), signed = a)) { case Left(err) =>
|
|
||||||
inside(err) { case SError.SErrorDamlException(FailedAuthorization(_, why)) =>
|
|
||||||
inside(why) { case cma: CreateMissingAuthorization =>
|
|
||||||
cma.authorizingParties shouldBe Set(b)
|
|
||||||
cma.requiredParties shouldBe Set(a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
"Sequence1" - {
|
|
||||||
|
|
||||||
"sequence1: A-> ( {B}->B ; ->A ) [OK]" in {
|
|
||||||
inside(
|
|
||||||
makeSequence1(
|
|
||||||
committers = Set(a),
|
|
||||||
required = Set(b),
|
|
||||||
signed1 = b,
|
|
||||||
signed2 = a,
|
|
||||||
)
|
|
||||||
) { case Right((tx, ars)) =>
|
|
||||||
val shape = shapeOfTransaction(tx)
|
|
||||||
val expected = List[Shape](Authority(Set(b), List(Create(b))), Create(a))
|
|
||||||
shape shouldBe expected
|
|
||||||
ars shouldBe List(AuthRequest(holding = Set(a), requesting = Set(b)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"sequence1: A-> ( {B}->B ; ->B ) [FAIL]" in {
|
|
||||||
inside(
|
|
||||||
makeSequence1(
|
|
||||||
committers = Set(a),
|
|
||||||
required = Set(b),
|
|
||||||
signed1 = b,
|
|
||||||
signed2 = b,
|
|
||||||
)
|
|
||||||
) { case Left(err) =>
|
|
||||||
inside(err) { case SError.SErrorDamlException(FailedAuthorization(_, why)) =>
|
|
||||||
inside(why) { case cma: CreateMissingAuthorization =>
|
|
||||||
cma.authorizingParties shouldBe Set(a)
|
|
||||||
cma.requiredParties shouldBe Set(b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"sequence1: A-> ( {A}->A ; ->A ) [OK; no auth-node]" in {
|
|
||||||
inside(
|
|
||||||
makeSequence1(
|
|
||||||
committers = Set(a),
|
|
||||||
required = Set(a),
|
|
||||||
signed1 = a,
|
|
||||||
signed2 = a,
|
|
||||||
)
|
|
||||||
) { case Right((tx, ars)) =>
|
|
||||||
val shape = shapeOfTransaction(tx)
|
|
||||||
val expected = List[Shape](Create(a), Create(a))
|
|
||||||
shape shouldBe expected
|
|
||||||
ars shouldBe List()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"sequence1: {A,B}-> ( {B}->B ; ->A ) [OK; no auth-node]" in {
|
|
||||||
inside(
|
|
||||||
makeSequence1(
|
|
||||||
committers = Set(a, b),
|
|
||||||
required = Set(b),
|
|
||||||
signed1 = b,
|
|
||||||
signed2 = a,
|
|
||||||
)
|
|
||||||
) { case Right((tx, ars)) =>
|
|
||||||
val shape = shapeOfTransaction(tx)
|
|
||||||
val expected = List[Shape](Create(b), Create(a))
|
|
||||||
shape shouldBe expected
|
|
||||||
ars shouldBe List()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"sequence1: {A,B}-> ( {B}->B ; ->B ) [OK; no auth-node]" in {
|
|
||||||
inside(
|
|
||||||
makeSequence1(
|
|
||||||
committers = Set(a, b),
|
|
||||||
required = Set(b),
|
|
||||||
signed1 = b,
|
|
||||||
signed2 = b,
|
|
||||||
)
|
|
||||||
) { case Right((tx, ars)) =>
|
|
||||||
val shape = shapeOfTransaction(tx)
|
|
||||||
val expected = List[Shape](Create(b), Create(b))
|
|
||||||
shape shouldBe expected
|
|
||||||
ars shouldBe List()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
"Sequence2" - {
|
|
||||||
|
|
||||||
"sequence2: A-> ( {B}->B ; {C}->C ) [OK; 2 auth nodes]" in {
|
|
||||||
inside(
|
|
||||||
makeSequence2(
|
|
||||||
committers = Set(a),
|
|
||||||
required1 = Set(b),
|
|
||||||
signed1 = b,
|
|
||||||
required2 = Set(c),
|
|
||||||
signed2 = c,
|
|
||||||
)
|
|
||||||
) { case Right((tx, ars)) =>
|
|
||||||
val shape = shapeOfTransaction(tx)
|
|
||||||
val expected = List(Authority(Set(b), List(Create(b))), Authority(Set(c), List(Create(c))))
|
|
||||||
shape shouldBe expected
|
|
||||||
ars shouldBe List(
|
|
||||||
AuthRequest(holding = Set(a), requesting = Set(b)),
|
|
||||||
AuthRequest(holding = Set(a), requesting = Set(c)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"sequence2: A-> ( {B}->B ; {B}->B ) [OK; 2 auth nodes]" in {
|
|
||||||
inside(
|
|
||||||
makeSequence2(
|
|
||||||
committers = Set(a),
|
|
||||||
required1 = Set(b),
|
|
||||||
signed1 = b,
|
|
||||||
required2 = Set(b),
|
|
||||||
signed2 = b,
|
|
||||||
)
|
|
||||||
) { case Right((tx, ars)) =>
|
|
||||||
val shape = shapeOfTransaction(tx)
|
|
||||||
val expected = List(Authority(Set(b), List(Create(b))), Authority(Set(b), List(Create(b))))
|
|
||||||
shape shouldBe expected
|
|
||||||
ars shouldBe List(
|
|
||||||
AuthRequest(holding = Set(a), requesting = Set(b)),
|
|
||||||
AuthRequest(holding = Set(a), requesting = Set(b)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"sequence2: A-> ( {B}->B ; {A}->A ) [OK; only 1 auth node]" in {
|
|
||||||
inside(
|
|
||||||
makeSequence2(
|
|
||||||
committers = Set(a),
|
|
||||||
required1 = Set(b),
|
|
||||||
signed1 = b,
|
|
||||||
required2 = Set(a),
|
|
||||||
signed2 = a,
|
|
||||||
)
|
|
||||||
) { case Right((tx, ars)) =>
|
|
||||||
val shape = shapeOfTransaction(tx)
|
|
||||||
val expected = List[Shape](Authority(Set(b), List(Create(b))), Create(a))
|
|
||||||
shape shouldBe expected
|
|
||||||
ars shouldBe List(AuthRequest(holding = Set(a), requesting = Set(b)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"sequence2: A-> ( {B}->B ; {C}->A ) [FAIL]" in {
|
|
||||||
inside(
|
|
||||||
makeSequence2(
|
|
||||||
committers = Set(a),
|
|
||||||
required1 = Set(b),
|
|
||||||
signed1 = b,
|
|
||||||
required2 = Set(c),
|
|
||||||
signed2 = a,
|
|
||||||
)
|
|
||||||
) { case Left(err) =>
|
|
||||||
inside(err) { case SError.SErrorDamlException(FailedAuthorization(_, why)) =>
|
|
||||||
inside(why) { case cma: CreateMissingAuthorization =>
|
|
||||||
cma.authorizingParties shouldBe Set(c)
|
|
||||||
cma.requiredParties shouldBe Set(a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"sequence2: A-> ( {B}->B ; {C}->B ) [FAIL]" in {
|
|
||||||
inside(
|
|
||||||
makeSequence2(
|
|
||||||
committers = Set(a),
|
|
||||||
required1 = Set(b),
|
|
||||||
signed1 = b,
|
|
||||||
required2 = Set(c),
|
|
||||||
signed2 = b,
|
|
||||||
)
|
|
||||||
) { case Left(err) =>
|
|
||||||
inside(err) { case SError.SErrorDamlException(FailedAuthorization(_, why)) =>
|
|
||||||
inside(why) { case cma: CreateMissingAuthorization =>
|
|
||||||
cma.authorizingParties shouldBe Set(c)
|
|
||||||
cma.requiredParties shouldBe Set(b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
"Nested" - {
|
|
||||||
|
|
||||||
"nested: A->{B}->{C}->C [OK]" in {
|
|
||||||
inside(makeNested(committers = Set(a), outer = Set(b), inner = Set(c), signed = c)) {
|
|
||||||
case Right((tx, ars)) =>
|
|
||||||
val shape = shapeOfTransaction(tx)
|
|
||||||
val expected = List(Authority(Set(b), List(Authority(Set(c), List(Create(c))))))
|
|
||||||
shape shouldBe expected
|
|
||||||
ars shouldBe List(
|
|
||||||
AuthRequest(holding = Set(a), requesting = Set(b)),
|
|
||||||
AuthRequest(holding = Set(b), requesting = Set(c)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"nested: A->{B}->{C}->A [FAIL]" in {
|
|
||||||
inside(makeNested(committers = Set(a), outer = Set(b), inner = Set(c), signed = a)) {
|
|
||||||
case Left(err) =>
|
|
||||||
inside(err) { case SError.SErrorDamlException(FailedAuthorization(_, why)) =>
|
|
||||||
inside(why) { case cma: CreateMissingAuthorization =>
|
|
||||||
cma.authorizingParties shouldBe Set(c)
|
|
||||||
cma.requiredParties shouldBe Set(a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"nested: A->{B}->{C}->B [FAIL]" in {
|
|
||||||
inside(makeNested(committers = Set(a), outer = Set(b), inner = Set(c), signed = b)) {
|
|
||||||
case Left(err) =>
|
|
||||||
inside(err) { case SError.SErrorDamlException(FailedAuthorization(_, why)) =>
|
|
||||||
inside(why) { case cma: CreateMissingAuthorization =>
|
|
||||||
cma.authorizingParties shouldBe Set(c)
|
|
||||||
cma.requiredParties shouldBe Set(b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"nested: A->{A}->{C}->C [OK; 1 auth-node]" in {
|
|
||||||
inside(makeNested(committers = Set(a), outer = Set(a), inner = Set(c), signed = c)) {
|
|
||||||
case Right((tx, ars)) =>
|
|
||||||
val shape = shapeOfTransaction(tx)
|
|
||||||
val expected = List(Authority(Set(c), List(Create(c))))
|
|
||||||
shape shouldBe expected
|
|
||||||
ars shouldBe List(AuthRequest(holding = Set(a), requesting = Set(c)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"nested: A->{A}->{C}->A [FAIL]" in {
|
|
||||||
inside(makeNested(committers = Set(a), outer = Set(a), inner = Set(c), signed = a)) {
|
|
||||||
case Left(err) =>
|
|
||||||
inside(err) { case SError.SErrorDamlException(FailedAuthorization(_, why)) =>
|
|
||||||
inside(why) { case cma: CreateMissingAuthorization =>
|
|
||||||
cma.authorizingParties shouldBe Set(c)
|
|
||||||
cma.requiredParties shouldBe Set(a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"nested: A->{C}->{C}->C [OK; 1 auth-node]" in {
|
|
||||||
inside(makeNested(committers = Set(a), outer = Set(c), inner = Set(c), signed = c)) {
|
|
||||||
case Right((tx, ars)) =>
|
|
||||||
val shape = shapeOfTransaction(tx)
|
|
||||||
val expected = List(Authority(Set(c), List(Create(c))))
|
|
||||||
shape shouldBe expected
|
|
||||||
ars shouldBe List(AuthRequest(holding = Set(a), requesting = Set(c)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"nested: A->{C}->{C}->A [FAIL]" in {
|
|
||||||
inside(makeNested(committers = Set(a), outer = Set(c), inner = Set(c), signed = a)) {
|
|
||||||
case Left(err) =>
|
|
||||||
inside(err) { case SError.SErrorDamlException(FailedAuthorization(_, why)) =>
|
|
||||||
inside(why) { case cma: CreateMissingAuthorization =>
|
|
||||||
cma.authorizingParties shouldBe Set(c)
|
|
||||||
cma.requiredParties shouldBe Set(a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"nested: A->{A,B}->{B,C}->C [OK]" in {
|
|
||||||
inside(makeNested(committers = Set(a), outer = Set(a, b), inner = Set(b, c), signed = c)) {
|
|
||||||
case Right((tx, ars)) =>
|
|
||||||
val shape = shapeOfTransaction(tx)
|
|
||||||
val expected = List(Authority(Set(a, b), List(Authority(Set(b, c), List(Create(c))))))
|
|
||||||
shape shouldBe expected
|
|
||||||
ars shouldBe List(
|
|
||||||
AuthRequest(holding = Set(a), requesting = Set(b)),
|
|
||||||
AuthRequest(holding = Set(a, b), requesting = Set(c)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"nested: A->{A,B}->{B,C}->B [OK]" in {
|
|
||||||
inside(makeNested(committers = Set(a), outer = Set(a, b), inner = Set(b, c), signed = b)) {
|
|
||||||
case Right((tx, ars)) =>
|
|
||||||
val shape = shapeOfTransaction(tx)
|
|
||||||
val expected = List(Authority(Set(a, b), List(Authority(Set(b, c), List(Create(b))))))
|
|
||||||
shape shouldBe expected
|
|
||||||
ars shouldBe List(
|
|
||||||
AuthRequest(holding = Set(a), requesting = Set(b)),
|
|
||||||
AuthRequest(holding = Set(a, b), requesting = Set(c)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"nested: A->{A,B}->{B,C}->A [FAIL]" in {
|
|
||||||
inside(makeNested(committers = Set(a), outer = Set(a, b), inner = Set(b, c), signed = a)) {
|
|
||||||
case Left(err) =>
|
|
||||||
inside(err) { case SError.SErrorDamlException(FailedAuthorization(_, why)) =>
|
|
||||||
inside(why) { case cma: CreateMissingAuthorization =>
|
|
||||||
cma.authorizingParties shouldBe Set(b, c)
|
|
||||||
cma.requiredParties shouldBe Set(a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO #15882 -- test interaction between Authority and Exercise/Rollback nodes
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
object WithAuthorityTest {
|
|
||||||
|
|
||||||
import SpeedyTestLib.loggingContext
|
|
||||||
import SpeedyTestLib.AuthRequest
|
|
||||||
|
|
||||||
val transactionSeed = crypto.Hash.hashPrivateKey("WithAuthorityTest.scala")
|
|
||||||
|
|
||||||
val pkgs: PureCompiledPackages = SpeedyTestLib.typeAndCompile(p"""
|
|
||||||
module M {
|
|
||||||
|
|
||||||
record @serializable T1 = { signed: Party, info: Int64 } ;
|
|
||||||
template (record : T1) = {
|
|
||||||
precondition True;
|
|
||||||
signatories Cons @Party [M:T1 {signed} record] (Nil @Party);
|
|
||||||
observers Nil @Party;
|
|
||||||
agreement "Agreement";
|
|
||||||
};
|
|
||||||
|
|
||||||
val single : List Party -> Party -> Update Unit =
|
|
||||||
\(requested: List Party) -> \(signed: Party) ->
|
|
||||||
WITH_AUTHORITY @Unit requested
|
|
||||||
(ubind x1: ContractId M:T1 <- create @M:T1 M:T1 { signed = signed, info = 100 }
|
|
||||||
in upure @Unit ());
|
|
||||||
|
|
||||||
val nested : List Party -> List Party -> Party -> Update Unit =
|
|
||||||
\(outer: List Party) -> \(inner: List Party) -> \(signed: Party) ->
|
|
||||||
WITH_AUTHORITY @Unit outer
|
|
||||||
(WITH_AUTHORITY @Unit inner
|
|
||||||
(ubind x1: ContractId M:T1 <- create @M:T1 M:T1 { signed = signed, info = 100 }
|
|
||||||
in upure @Unit ()));
|
|
||||||
|
|
||||||
val sequence1 : List Party -> Party -> Party -> Update Unit =
|
|
||||||
\(required1: List Party) -> \(signed1: Party) -> \(signed2: Party) ->
|
|
||||||
ubind
|
|
||||||
u: Unit <-
|
|
||||||
WITH_AUTHORITY @Unit required1
|
|
||||||
(ubind x1: ContractId M:T1 <- create @M:T1 M:T1 { signed = signed1, info = 100 }
|
|
||||||
in upure @Unit ());
|
|
||||||
x2: ContractId M:T1 <- create @M:T1 M:T1 { signed = signed2, info = 100 }
|
|
||||||
in upure @Unit ();
|
|
||||||
|
|
||||||
val sequence2 : List Party -> Party -> List Party -> Party -> Update Unit =
|
|
||||||
\(required1: List Party) -> \(signed1: Party) -> \(required2: List Party) -> \(signed2: Party) ->
|
|
||||||
ubind
|
|
||||||
u: Unit <-
|
|
||||||
WITH_AUTHORITY @Unit required1
|
|
||||||
(ubind x1: ContractId M:T1 <- create @M:T1 M:T1 { signed = signed1, info = 100 }
|
|
||||||
in upure @Unit ());
|
|
||||||
u: Unit <-
|
|
||||||
WITH_AUTHORITY @Unit required2
|
|
||||||
(ubind x2: ContractId M:T1 <- create @M:T1 M:T1 { signed = signed2, info = 100 }
|
|
||||||
in upure @Unit ())
|
|
||||||
in upure @Unit ();
|
|
||||||
}
|
|
||||||
""")
|
|
||||||
|
|
||||||
def makeSetPartyValue(set: Set[Party]): SValue = {
|
|
||||||
SList(FrontStack(set.toList.map(SParty(_)): _*))
|
|
||||||
}
|
|
||||||
|
|
||||||
type Success = (SubmittedTransaction, List[AuthRequest])
|
|
||||||
|
|
||||||
def makeSingle(
|
|
||||||
committers: Set[Party],
|
|
||||||
required: Set[Party],
|
|
||||||
signed: Party,
|
|
||||||
): Either[SError, Success] = {
|
|
||||||
val requiredV = makeSetPartyValue(required)
|
|
||||||
val signedV = SParty(signed)
|
|
||||||
val example = SEApp(pkgs.compiler.unsafeCompile(e"M:single"), Array(requiredV, signedV))
|
|
||||||
val machine = Speedy.Machine.fromUpdateSExpr(pkgs, transactionSeed, example, committers)
|
|
||||||
SpeedyTestLib.buildTransactionCollectAuthRequests(machine)
|
|
||||||
}
|
|
||||||
|
|
||||||
def makeSequence1(
|
|
||||||
committers: Set[Party],
|
|
||||||
required: Set[Party],
|
|
||||||
signed1: Party,
|
|
||||||
signed2: Party,
|
|
||||||
): Either[SError, Success] = {
|
|
||||||
val requiredV = makeSetPartyValue(required)
|
|
||||||
val signed1V = SParty(signed1)
|
|
||||||
val signed2V = SParty(signed2)
|
|
||||||
val example = SEApp(
|
|
||||||
pkgs.compiler.unsafeCompile(e"M:sequence1"),
|
|
||||||
Array(requiredV, signed1V, signed2V),
|
|
||||||
)
|
|
||||||
val machine = Speedy.Machine.fromUpdateSExpr(pkgs, transactionSeed, example, committers)
|
|
||||||
SpeedyTestLib.buildTransactionCollectAuthRequests(machine)
|
|
||||||
}
|
|
||||||
|
|
||||||
def makeSequence2(
|
|
||||||
committers: Set[Party],
|
|
||||||
required1: Set[Party],
|
|
||||||
signed1: Party,
|
|
||||||
required2: Set[Party],
|
|
||||||
signed2: Party,
|
|
||||||
): Either[SError, Success] = {
|
|
||||||
val required1V = makeSetPartyValue(required1)
|
|
||||||
val signed1V = SParty(signed1)
|
|
||||||
val required2V = makeSetPartyValue(required2)
|
|
||||||
val signed2V = SParty(signed2)
|
|
||||||
val example = SEApp(
|
|
||||||
pkgs.compiler.unsafeCompile(e"M:sequence2"),
|
|
||||||
Array(required1V, signed1V, required2V, signed2V),
|
|
||||||
)
|
|
||||||
val machine = Speedy.Machine.fromUpdateSExpr(pkgs, transactionSeed, example, committers)
|
|
||||||
SpeedyTestLib.buildTransactionCollectAuthRequests(machine)
|
|
||||||
}
|
|
||||||
|
|
||||||
def makeNested(
|
|
||||||
committers: Set[Party],
|
|
||||||
outer: Set[Party],
|
|
||||||
inner: Set[Party],
|
|
||||||
signed: Party,
|
|
||||||
): Either[SError, Success] = {
|
|
||||||
val outerV = makeSetPartyValue(outer)
|
|
||||||
val innerV = makeSetPartyValue(inner)
|
|
||||||
val signedV = SParty(signed)
|
|
||||||
val example = SEApp(pkgs.compiler.unsafeCompile(e"M:nested"), Array(outerV, innerV, signedV))
|
|
||||||
val machine = Speedy.Machine.fromUpdateSExpr(pkgs, transactionSeed, example, committers)
|
|
||||||
SpeedyTestLib.buildTransactionCollectAuthRequests(machine)
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed trait Shape // minimal transaction tree, for purposes of writing test expectation
|
|
||||||
final case class Create(signed: Party) extends Shape
|
|
||||||
final case class Exercise(x: List[Shape]) extends Shape
|
|
||||||
final case class Rollback(x: List[Shape]) extends Shape
|
|
||||||
final case class Authority(obtained: Set[Party], x: List[Shape]) extends Shape
|
|
||||||
|
|
||||||
private def shapeOfTransaction(tx: SubmittedTransaction): List[Shape] = {
|
|
||||||
def trees(nid: NodeId): List[Shape] = {
|
|
||||||
tx.nodes(nid) match {
|
|
||||||
case create: Node.Create =>
|
|
||||||
create.arg match {
|
|
||||||
case ValueRecord(_, ImmArray((None, ValueParty(signed)), _)) =>
|
|
||||||
List(Create(signed))
|
|
||||||
case _ =>
|
|
||||||
sys.error(s"unexpected create.arg: ${create.arg}")
|
|
||||||
}
|
|
||||||
case _: Node.LeafOnlyAction =>
|
|
||||||
Nil
|
|
||||||
case node: Node.Exercise =>
|
|
||||||
List(Exercise(node.children.toList.flatMap(nid => trees(nid))))
|
|
||||||
case node: Node.Rollback =>
|
|
||||||
List(Rollback(node.children.toList.flatMap(nid => trees(nid))))
|
|
||||||
case node: Node.Authority =>
|
|
||||||
List(Authority(node.obtained, node.children.toList.flatMap(nid => trees(nid))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tx.roots.toList.flatMap(nid => trees(nid))
|
|
||||||
}
|
|
||||||
}
|
|
@ -457,10 +457,6 @@ object Ast {
|
|||||||
final case object BFoldl extends BuiltinFunction // : ∀a b. (b → a → b) → b → List a → b
|
final case object BFoldl extends BuiltinFunction // : ∀a b. (b → a → b) → b → List a → b
|
||||||
final case object BFoldr extends BuiltinFunction // : ∀a b. (a → b → b) → b → List a → b
|
final case object BFoldr extends BuiltinFunction // : ∀a b. (a → b → b) → b → List a → b
|
||||||
|
|
||||||
// Authority
|
|
||||||
final case object BWithAuthority
|
|
||||||
extends BuiltinFunction // : ∀ a. List Party → Update a → Update a
|
|
||||||
|
|
||||||
// Maps
|
// Maps
|
||||||
final case object BTextMapEmpty extends BuiltinFunction // : ∀ a. TextMap a
|
final case object BTextMapEmpty extends BuiltinFunction // : ∀ a. TextMap a
|
||||||
final case object BTextMapInsert
|
final case object BTextMapInsert
|
||||||
|
@ -338,7 +338,6 @@ private[parser] class ExprParser[P](parserParameters: ParserParameters[P]) {
|
|||||||
"UNIX_MICROSECONDS_TO_TIMESTAMP" -> BUnixMicrosecondsToTimestamp,
|
"UNIX_MICROSECONDS_TO_TIMESTAMP" -> BUnixMicrosecondsToTimestamp,
|
||||||
"FOLDL" -> BFoldl,
|
"FOLDL" -> BFoldl,
|
||||||
"FOLDR" -> BFoldr,
|
"FOLDR" -> BFoldr,
|
||||||
"WITH_AUTHORITY" -> BWithAuthority,
|
|
||||||
"TEXTMAP_EMPTY" -> BTextMapEmpty,
|
"TEXTMAP_EMPTY" -> BTextMapEmpty,
|
||||||
"TEXTMAP_INSERT" -> BTextMapInsert,
|
"TEXTMAP_INSERT" -> BTextMapInsert,
|
||||||
"TEXTMAP_LOOKUP" -> BTextMapLookup,
|
"TEXTMAP_LOOKUP" -> BTextMapLookup,
|
||||||
|
@ -209,7 +209,6 @@ class ParsersSpec extends AnyWordSpec with ScalaCheckPropertyChecks with Matcher
|
|||||||
"UNIX_MICROSECONDS_TO_TIMESTAMP" -> BUnixMicrosecondsToTimestamp,
|
"UNIX_MICROSECONDS_TO_TIMESTAMP" -> BUnixMicrosecondsToTimestamp,
|
||||||
"FOLDL" -> BFoldl,
|
"FOLDL" -> BFoldl,
|
||||||
"FOLDR" -> BFoldr,
|
"FOLDR" -> BFoldr,
|
||||||
"WITH_AUTHORITY" -> BWithAuthority,
|
|
||||||
"EXPLODE_TEXT" -> BExplodeText,
|
"EXPLODE_TEXT" -> BExplodeText,
|
||||||
"IMPLODE_TEXT" -> BImplodeText,
|
"IMPLODE_TEXT" -> BImplodeText,
|
||||||
"APPEND_TEXT" -> BAppendText,
|
"APPEND_TEXT" -> BAppendText,
|
||||||
|
@ -4557,15 +4557,6 @@ List functions
|
|||||||
predicate give as first argument.
|
predicate give as first argument.
|
||||||
|
|
||||||
|
|
||||||
Authority functions
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
* ``WITH_AUTHORITY : ∀ (α : ⋆) . 'List' 'Party' → 'Update' α → 'Update' α``
|
|
||||||
|
|
||||||
Request authorization from the ledger for the scope of an update operation.
|
|
||||||
|
|
||||||
[*Available in versions >= 1.dev*]
|
|
||||||
|
|
||||||
Text map functions
|
Text map functions
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -22,3 +22,7 @@ template T
|
|||||||
withAuthorityOf [party2] $ do
|
withAuthorityOf [party2] $ do
|
||||||
create (HaveAuthority party2)
|
create (HaveAuthority party2)
|
||||||
pure ()
|
pure ()
|
||||||
|
|
||||||
|
|
||||||
|
withAuthorityOf : [Party] -> Update a -> Update a
|
||||||
|
withAuthorityOf _ u = u -- TODO #15882 -- require rework
|
||||||
|
@ -137,12 +137,6 @@ private[validation] object Typing {
|
|||||||
alpha.name -> KStar,
|
alpha.name -> KStar,
|
||||||
TForall(beta.name -> KStar, (alpha ->: beta ->: beta) ->: beta ->: TList(alpha) ->: beta),
|
TForall(beta.name -> KStar, (alpha ->: beta ->: beta) ->: beta ->: TList(alpha) ->: beta),
|
||||||
),
|
),
|
||||||
// Authority
|
|
||||||
BWithAuthority ->
|
|
||||||
TForall(
|
|
||||||
alpha.name -> KStar,
|
|
||||||
TList(TParty) ->: TUpdate(alpha) ->: TUpdate(alpha),
|
|
||||||
),
|
|
||||||
// Maps
|
// Maps
|
||||||
BTextMapEmpty ->
|
BTextMapEmpty ->
|
||||||
TForall(
|
TForall(
|
||||||
|
@ -32,6 +32,8 @@ template ProposeConsortiumAuthority
|
|||||||
withAuthorityOf [consortiumParty] $ do
|
withAuthorityOf [consortiumParty] $ do
|
||||||
create HasConsortiumAutority with consortiumParty
|
create HasConsortiumAutority with consortiumParty
|
||||||
|
|
||||||
|
withAuthorityOf : [Party] -> Update a -> Update a
|
||||||
|
withAuthorityOf _ u = u -- TODO #15882 -- require rework
|
||||||
|
|
||||||
test : Script ()
|
test : Script ()
|
||||||
test = do
|
test = do
|
||||||
@ -46,7 +48,8 @@ test = do
|
|||||||
proposer = alice
|
proposer = alice
|
||||||
accepted = []
|
accepted = []
|
||||||
obs = [bob,charlie]
|
obs = [bob,charlie]
|
||||||
consortiumParty = org
|
--consortiumParty = org -- TODO #15882 -- require rework
|
||||||
|
consortiumParty = alice
|
||||||
|
|
||||||
prop <- submit bob do exerciseCmd prop Accept with who = bob
|
prop <- submit bob do exerciseCmd prop Accept with who = bob
|
||||||
prop <- submit charlie do exerciseCmd prop Accept with who = charlie
|
prop <- submit charlie do exerciseCmd prop Accept with who = charlie
|
||||||
|
Loading…
Reference in New Issue
Block a user