Version 13 (modified by 13 years ago) (diff) | ,
---|
GENI Aggregate Manager API Draft Revisions
This page documents DRAFT revisions to the GENI Aggregate Manager API, proposed for the next version of the API. As indicated below, many of the revisions documented here have been agreed to in discussions on the GENI developer mailing list, and during at least one GEC, but not formally adopted. Well behaved aggregates will typically already implement such revisions. Other revisions are in early discussions and subject to change or abandonment.
The GENI Aggregate Manager API allows aggregates to advertise resources and to allocate resources to Slices in the form of Slivers. A Sliver is the set of resources allocated by one Aggregate to one Slice.
The current officially adopted version of the API is 1 and is documented on the main API page here.
This page documents proposed changes for AM API version 2. These changes are grouped into sets. API Version 2 will be the collection of changes from the change sets below which we next agree on. Change sets still under discussion will then be targeted at a future release.
- Agreed upon and generally implemented: RSpec related changes, specifying that RSpecs are XML following GENI standard schemas.
- Since June 2011, the latest software from ProtoGENI and SFA (as of code tag 1.0-24) has complied with these changes.
- Omni version 1.3 (released June 2011) added client software support for these changes.
- New and changing proposal: Supporting flexible arguments and returns. Specifically, adding a property list to all calls, and making all returns be a property list.
- New and changing proposal: Add a new method: UpdateSliver
- Undefined: Support for clients manipulating individual slivers or groups of slivers at an aggregate
- Undefined: Tickets, otherwise known as negotiated reservations.
Summary of Proposed Changes
Change Set A: RSpecs are XML documents following GENI schemas
This change set has been discussed and well behaved aggregates already implement this change.
- Specify that GENI RSpecs comply with GENI standard XML schemas as posted at http://www.geni.net/resources/rspec. GENI RSpec V3 is what was the ProtoGENI V2 schemas as documented here.
- Include additional options in GetVersion and ListResources to allow aggregates to support the GENI RSpecs in addition to their own native format.
Change Set B: Flexible arguments and returns
This change set is new, not implemented, and currently under discussion.
- All methods take an options argument, which is a non null XML struct. No required options are added with this change - the struct may be empty.
- Method returns are modified to return at least 3 name/value pairs, with arbitrary additional such pairs.
code
is an integer, with non-0 indicating error.value
is the return value as specified in AM API V1 (RSpec, etc), andoutput
is a human readable indication of the nature of the return or error.- Aggregates are free to use other additional name/value pairs in the return struct.
Change Set C: UpdateSliver
This change set is new, not implemented, and currently under discussion.
- Add a method UpdateSliver, which adds, removes or modifies resources allocated the slice at the given aggregate, to match the new request RSpec supplied as an argument
- See the discussion below.
Change Set D: Slivers and Sliver groups
This change is TBD. The current proposal is to do nothing. See the discussion below.
Change Set E: Tickets
This change is TBD. There is no concrete proposal yet on how to introduce tickets. See the discussion below.
Proposing Additional Changes
GENI community members are encouraged to propose changes to the GENI Aggregate Manager API.
Technical discussions are generally held on the Developers mailing list
Specific questions may be directed to the software team at the GPO (Tom Mitchell, Aaron Helsinger, and Sarah Edwards) at {tmitchel, ahelsing, sedwards} at geni.net
Proposed Change Details
Change Set A
Note: The change to GENI standard RSpec schemas originally referenced ProtoGENI V2 RSpec schemas, hosted at www.protogeni.net. These schemas have now been re-branded as GENI V3 RSpec schemas and are hosted at http://www.geni.net/resources/rspec/3.
Note: Options in the geni_ namespace remain reserved, but not all GENI standard options need to be named with the geni_ prefix.
Note: Changes described here have been discussed, are generally agreed upon, and are implemented at well behaved aggregates and clients.
Part 1: Standardized XML-based GENI RSpecs
At GEC10 the GENI community agreed that GENI RSpecs would be in what was the ProtoGENI V2 format and is now known as GENI V3. Aggregates are free to use an alternate format internally, but must accept and produce compliant RSpecs on demand. Note that individual aggregates may use RSpec extensions to describe custom resources or properties of resources. For RSpec extension information, see the ProtoGENI wiki.
For more information:
- Official GENI V3 RSpec schemas
- GENI standard (was ProtoGENI V2) format
- RSpec extension information
- RSpec schemas listing
Specific changes include:
- ListResources: Return value of ListResources remains an XMLRPC string, but its format and meaning are now proscribed.
The return value is an RSpec matching the GENI standard RSpec in text format if
geni_compressed
is unspecified or set tofalse
. The return value will be a ZLib compressed and then base 64 encoded string representation of the RSpec ifgeni_compressed
is specified and set totrue
.
This RSpec will be a advertisement RSpec when invoked with no geni_slice_urn
option, representing the resources available at this aggregate. When the client supplies the geni_slice_urn
option, then the aggregate will return a manifest RSpec, representing all resources allocated to that slice by this aggregate.
- CreateSliver: rspec argument remains an XMLRPC string, but its format and meaning are now proscribed.
rspec
-
An RSpec matching the GENI standard request RSpec schema containing the resources that the caller is requesting for allocation to the slice specified in
slice_urn
. These are expected to be consistent with the resources returned by a previous invocation of ListResources.
- CreateSliver: return value remains an XMLRPC string, but its format and meaning are now proscribed.
The return value is an RSpec matching the GENI standard manifest RSpec schema indicating the resources that were allocated to the slice. The result RSpec may contain additional information about the allocated resources.
Part 2: New RSpec Version Options
In order to allow aggregates to support both a native RSpec format (e.g. the standard PlanetLab / SFA RSpecs) as well as the GENI-standard format (GENI V3, was ProtoGENI V2), we need new options to allow a client to request RSpecs in a particular format.
Specifically, aggregates will advertise (in GetVersion) the list of Advertisement and Request RSpec types they are willing to accept, as well as the default Advertisement RSpec type. And they will produce manifest RSpecs in a format matching the format of the CreateSliver input request RSpec (e.g. return a GENI V3 manifest RSpec when given a GENI V3 request RSpec, and a native PlanetLab manifest RSpec when given a PlanetLab request RSpec).
Contract details
Aggregates advertise the type
and version
of RSpec formats that they support. If available, they specify the schema
, namespace
and extensions
combination which is the authoritative definition of that format. Clients of the API should understand that combination in order to know how to understand the resources available at that aggregate.
If an aggregate advertises a particular type
/version
(optionally defined with a combination of schema
, namespace
and extensions
) in the ad_rspec_versions
attribute of GetVersion, then it promises to send a correct Advertisement RSpec in response to a ListResources call which supplies an rspec_version
option containing that type
/version
. (rspec_version
is a struct
with 2 members, type
and version
. type
and version
are case-insensitive strings, matching those in ad_rspec_versions
).
If an Aggregate advertises a particular type
/version
(optionally defined with a combination of schema
, namespace
and extensions
) in the request_rspec_versions
attribute of GetVersion then it promises to correctly honor a CreateSliver call containing a request RSpec in the given format, and then to return a Manifest RSpec in the corresponding format (i.e. a GENI format request is answered with a GENI format manifest). The aggregate also promises to send a correctly formatted Manifest RSpec in response to a ListResources call which supplies a valid geni_slice_urn
option and an rspec_version
option containing that supported type
/version
.
The GetVersion attribute default_ad_rspec
will be one of the values in the GetVersion ad_rspec_versions
array.
New GetVersion required attributes
Return the version of the GENI Aggregate API and RSpecs supported by this aggregate.
struct GetVersion()
The result is an XMLRPC struct with at least the following members:
{ int geni_api; array request_rspec_versions of { string type; string version; string schema; string namespace; array extensions of string; }; array ad_rspec_versions of { string type; string version; string schema; string namespace; array extensions of string; }; default_ad_rspec of { string type; string version; }; }
geni_api
- An integer indicating the revision of the Aggregate Manager API that an aggregate supports. This document (DRAFT revisions) describes API version 2 (two).
request_rspec_versions
- An array of data structures indicating the RSpec types accepted by this AM in a request.
ad_rspec_versions
- An array of data structures indicating what types of RSpec advertisements may be produced by this AM in ListResources.
default_ad_rspec
-
A data structure indicating the default type of advertisement RSpec produced by this AM in ListResources. Matches one of the values from
ad_rspec_versions
Elements used within request_rspec_versions
, ad_rspec_versions
, and default_ad_rspec
:
type
,version
-
Two case-insensitive strings which together comprise the type of RSpec. The RSpec
type
should be one of "geni", "protogeni", "sfa", "orca", "openflow", or "orbit" andversion
should be a type-specific version identifier as specified by the appropriate control framework. The "geni" type is reserved for GENI standard format RSpecs, following the schemas hosted at www.geni.net.
schema
- An optional URL pointing to a schema which can be used to verify the given type of RSpec.
namespace
- An optional XML namespace which the RSpec of the given type belongs to.
extensions
- An array of aggregate-specific strings denoting which extensions are supported. In the case of ProtoGENI, these are XML namespaces which denote the extension as a whole.
Implementations can add additional members to the struct as desired. Implementations should choose an appropriate prefix to avoid conflicts, but avoid geni_
which should be reserved for common options.
This operation is similar to ProtoGENI's GetVersion operation. The SFA specification does not include this operation other than through this method.
New ListResources Option
ListResources will take an additional option, rspec_version
, allowing a user to request an Advertisement or Manifest Rspec in a particular format. This struct must contain a type
and version
matching one of this Aggregate's advertised ad_rspec_versions
.
Specifics:
Return information about available resources or resources allocated to a slice.
string ListResources(string credentials[], struct options)
....
options
-
An XMLRPC struct containing members indicating the set of resources the caller is interested in or the format of the result. In addition to the members specified below, callers can pass additional members that specific aggregate manager implementations might honor. Implementations should choose an appropriate prefix to avoid conflicts, but avoid
geni_
which should be reserved for common options.
The following members are available for use in the options parameter. All aggregate managers are required to implement these options.
{ boolean geni_available; boolean geni_compressed; string geni_slice_urn; struct rspec_version { string type; string version; }; }
....
rspec_version
-
An XMLRPC struct indicating the type and version of Advertisement or Manifest RSpec to return. The struct contains 2 members,
type
andversion
.type
andversion
are case-insensitive strings, matching those inad_rspec_versions
as returned by GetVersion at this aggregate.
If this option is not included in the request, then the returned RSpec will be of the type specified in
default_ad_rspec
. That Rspec will be an Advertisement RSpec when nogeni_slice_urn
option is supplied. When a validgeni_slice_urn
option is supplied, the returned RSpec will be a Manifest RSpec of the type corresponding todefault_ad_rspec
, but in manifest format.
If the aggregate cannot support the requested
type
/version
(that pair is not listed inad_rspec_versions
), then the aggregate returns an Exception.
New CreateSliver behavior
If an Aggregate advertises a type
/version
pair in its request_rspec_versions
as returned by GetVersion, then it promises to correctly honor a CreateSliver call containing a request RSpec in the given format, and then to return a Manifest RSpec in the corresponding format (ie a GENI V3 standard request is answered with a GENI V3 manifest).
Change Set B
Note: This set of 2 distinct changes is currently under discussion and has gotten no unofficial or official agreement.
Note: There are 2 parts to this change set. They could be adopted independently, but are described as going together. Additionally, they are described as cumulative to Change Set A above, but are independent.
Part 1: Additional options argument
Adding support for additional functionality in the AM API is currently difficult. Many possible areas of innovation are variations on existing functions. This change adds flexibility in arguments to support such innovation.
Under this proposal, each method will take an argument which is a set of name-value pairs (an XMLRPC struct, aka a property list). This argument is required for all methods except GetVersion (where it is optional), but may be empty (non NULL but containing no name/value pairs). Aggregates may support new entries in this 'options' argument to allow new non-standardized functionality.
Specifically, this change adds a final struct options
argument to each of GetVersion, CreateSliver, SliverStatus, RenewSliver, DeleteSliver, and Shutdown. ListResources already has that argument. The argument is optional for GetVersion, but required for all other functions.
Aggregates are compliant with this API change by accepting this argument; only for ListResources are they required to handle any specific options. Similarly, clients are required to supply this argument to talk to compatible aggregates, but are only required to supply any particular options for ListResources.
In GetVersion, this argument remains optional. Clients that only talk AM API V1 will get an error invoking most functions, when they leave off the options
argument. Experimenters can then call GetVersion (without the options
argument). AM API V2 compliant Aggregates shall include the geni_api
argument as a top-level entry in the return struct, specifying 2
to indicate to clients that this AM speaks version 2 of the AM API. This allows experimenters to understand that they need to upgrade their client, or might instruct a clever client tool to automatically switch to version 2 syntax.
Aggregates should not require any new options to any method - they should always have a reasonable default for any such option. Clients must always be able to work with any aggregate by simply supplying the options required by this API.
Aggregates are encouraged to document any new options which they accept in any method, to bootstrap coordination with clients, and provide documentation for human experimenters. One way to provide partial documentation, is to implement XML-RPC introspection. Through the use of method help, aggregates can provide human readable text describing options. Alternatively or additionally, aggregates may document options as part of their return from GetVersion. This allows clients to either avoid communicating with an aggregate for which the client does not understand how to provide those options, or to tailor the client's request to provide those extra options. We have not specified the format for advertising those extra options in GetVersion.
A sample possible option advertisement in GetVersion:
methodOptions: { GetVersion: { myNewOption1: { type=String, description="A useful but not critical option. This is a human parsable description." }, myOtherNewOption:..... }, ListResources.... }
Part 2: Richer return values
In AM API V1, method failures come back sometimes as XMLRPC Faults, sometimes as False, and is occasionally inconsistent across aggregates. Failures typically do not indicate how the Experimenter should modify their request for it to succeed, or if this is a server error. This proposed change expands and formalizes the return structures, to support semantically richer returns, allowing Experimenters better insight into both successes and failures, and how to respond.
Allowing aggregates to return more information, on both errors and success, will allow for a richer client-server communication. It would also allow aggregates to give clients hints on how to use successful returns, or otherwise innovate within the bounds of the AM API.
This change will modify all methods to return an XMLRPC struct (aka property list) on any application layer success, failure, and even on an error or for most exceptions. Note that a malformed XMLRPC request should still raise an XMLRPC Fault, and other Faults dictated by the XMLRPC specification should still be raised. This struct will contain the return value from the previous revision of the AM API as an entry. This struct will have 3 defined entries, and aggregates are free to include other entries to give more information to clients.
The three required entries in the return structure are code
, value
, and option
:
code
: An error code: integer, non-zero on error.- 0 = Success
- <0 = XMLRPC required error codes
- 1-1000 = GENI negotiated return codes (none so far)
- 1001-2000 = ProtoGENI specific return codes
- 2001-3000 = PlanetLab specific return codes
- 3001-4000 = Orca specific return codes
- 4001-5000 = OpenFlow specific return codes
- others as needed
value
: On success, this is required. Optional on failure or error. Object representing the successful return value. This will be the object previously returned by the function (for example the manifest RSpec for CreateSliver, or the struct for SliverStatus). The value is not defined on error, though aggregates are free to use it.- For GetVersion, the
value
is an XMLRPC struct - For ListResources, the
value
is an RSpec - For CreateSliver, the
value
is an RSpec - For RenewSliver, the
value
is a boolean - For DeleteSliver, the
value
is a boolean - For SliverStatus, the
value
is an XMLRPC struct - For Shutdown, the
value
is a boolean
- For GetVersion, the
option
: On failure or error, this is required. Optional on success. This is a String with a human readable message explaining the result. Specifically, this might include an error string, a stacktrace, or other useful messages to help the Experimenter resolve or report the failure or error. It is not defined on success, though aggregates are free to use it.
Aggregates are encouraged to use code
values and output
messages that help experimenters and tools distinguish between bad input, other experimenter error, temporary server errors, or server bugs.
Aggregates are similarly encouraged to provide hints on how to fix bad requests using the value
entry to experimenters on error or failures. For example, a failed RenewSliver call that failed because you are not allowed to renew your sliver that far in the future, might return a new date string in the value
field that would be allowed. Similarly, a failed CreateSliver call might return a modified request RSpec in the value
field.
Aggregates should avoid raising an error (XMLRPC Fault) for application layer errors or any other cases where the XMLRPC specification does not require a Fault, but rather should attempt to return this struct, providing any error messages and stack traces in the output
field or other additional fields.
For comparison, Orca functions return property lists internally. The ProtoGENI CMV2 API returns a struct with exactly these 3 values. ProtoGENI however uses a different range of return codes, and largely does not define the value
slot on errors.
For example, SliverStatus could return on success:
{ code: 0 value: { geni_urn: <sliver URN> geni_status: ready geni_resources: [ { geni_urn: <resource URN> geni_status: ready geni_error: ''}, { geni_urn: <resource URN> geni_status: ready geni_error: ''} ] } option: <none> }
On failure, DeleteSliver might return:
{ code: 1 value: False option: 'No such slice here' }
(That code and option are merely examples.)
An exception: At the top level, GetVersion adds a required entry: 'geni_api'=2. This allows V1 clients to determine that they are indeed talking to a GENI AM, but since the version is 2, that is why other function calls will fail.
Changes Summary: New Method Signatures
When taken together, the new method signatures would be:
struct GetVersion(options=None) Success Return: { geni_api = 2 code = 0 value { geni_api=2, methodOptions: { <contents of this are TBD, as per above> } <lots of other options follow> } option = <None> } struct ListResources(string credentials[], struct options) Success Return: { code=0 value= <GENI V3 Ad or Manifest RSpec string> option = <None> } struct CreateSliver(string slice_urn, string credentials[], <GENIV3 request RSpec schema compliant XML string> rspec, struct users[], struct options) Success Return: { code=0 value= <GENI V3 Manifest RSpec string> option = <None> } struct DeleteSliver(string slice_urn, string credentials[], struct options) Success Return: { code=0 value= boolean option = <None> } struct SliverStatus(string slice_urn, string credentials[], struct options) Success Return: { code=0 value= struct (as defined in V1) option = <None> } struct RenewSliver(string slice_urn, string credentials[], string expiration_time, struct options) Success Return: { code=0 value= boolean option = <None> } struct Shutdown(string slice_urn, string credentials[], struct options) Success Return: { code=0 value= boolean option = <None> }
Change Set C: UpdateSliver
Note: This set of changes is currently under active discussion and has gotten no unofficial or official agreement.
A common complaint among experimenters about the current AM API V1 is that there is no way to add or remove resources from a slice at an aggregate, without completely deleting the slice at that aggregate and recreating it, possibly losing resources to another experimenter and certainly losing state. This proposal aims to address that, by introducing a method to update the slice at an aggregate.
The SFA calls for an UpdateSlice method, "to request that additional resources—as specified in the RSpec—be allocated to the slice".
In the PlanetLab implementation of the SFA, UpdateSliver is in fact a synonym for CreateSliver - the server will ensure that your allocated resources match your request RSpec, adding, removing and modifying resources as needed. It immediately allocates and boots nodes to match the request RSpec.
The ProtoGENI CMV2 API has UpdateSliver, which is described as the way to "Request a change of resources for an existing sliver. The new set of resources that are desired are specified in the rspec." At ProtoGENI as at PlanetLab, this method takes the full RSpec description of resources the experimenter wants, and the server computes the difference with what the experimenter already has. At ProtoGENI though, this method returns a ticket. The experimenter must then redeem the ticket to actually acquire the resources. Then the experimenter manually calls RestartSliver as needed on nodes that need to be rebooted, when the experimenter is ready to do so. This takes an extra step, but gives the experimenter full control over which nodes are restarted and when.
Orca supports a modify function to modify properties of existing reserved resources. Similar functionality is in discussion to add or remove resources within a slice.
Here are some key properties and differences of this method at those first two aggregate code-bases, with a note on the alternatives. The community must discuss the options:
- In both ProtoGENI and PlanetLab, the method takes the full description of what the experimenter wants, and the server computes the difference. Note that 2 experimenters with permissions to modify the slice (say, 2 students of a professor) could issue conflicting update calls on the same aggregate. An alternative would be that experimenters must compute the difference themselves, and would just specify the incremental changes that they want in their reservation.
- Atomic: either the full request succeeds, or it fails. The alternative would be that if the experimenter wanted 5 more nodes and only 3 were available, then the server could give you those 3.
- ProtoGENI and PlanetLab differ on whether the changes are immediate or not. ProtoGENI uses tickets, allowing the experimenter to change their mind or coordinate their requests (See below). They also separate out reservation of the resources with restarting nodes. This allows the experimenter to control which nodes get rebooted and when. PlanetLab in comparison handles all restarting of nodes for the experimenters, giving them a single operation to get their resources. This approach also more closely matches the behavior of CreateSliver in the AM API V1.
The community must discuss the alternatives above.
The proposed new method:
struct UpdateSliver(string slice_urn, string credentials[], <GENIV3 request RSpec schema compliant XML string> rspec, struct users[], struct options) Success Return: { code=0 value= <GENI V3 Manifest RSpec string> option = <None> }
Proposed method semantics:
- RSpec argument is a complete request RSpec with the desired new end state for the slice at this aggregate. Open questions: Does the request schema support specifying sliver_ids or other attributes that were in the manifest RSpec, and which the experimenter might want or need to preserve in this RSpec?
- Atomic: the request either succeeds entirely or fails and the slice is not changed at the aggregate at all, with the aggregate returning a message indicating that it failed and why. Aggregates are encouraged to return enough information to allow the experimenter to modify the request such that it can succeed.
- Resources are allocated and started or restarted immediately, on behalf of the experimenter (no tickets, and no separate call to restart the sliver)
- The API provides no guarantees about whether existing resources in the slice at the aggregate will be left undisturbed or will be restarted. Aggregates should document any guarantees or the lack thereof for their resources. For example, an aggregate may move virtual machines from one physical rack to another in order to accommodate an experimenter's modified requirements for internal network topology or disk space.
Change Set D: Slivers and Sliver Groups
Note: This set of changes is currently under active discussion and has gotten no unofficial or official agreement.
The current proposal in this change set is to do nothing. See the proposal for UpdateSliver instead.
The current AM API calls take a Slice URN, and operate on all resources under that ID at the given aggregate - all the resources for that slice at the aggregate are allocated, renewed, and deleted together. There is no provision for releasing some of the resources allocated to the slice at that aggregate, or for adding new resources to the reservation for that slice at a given aggregate.
This ties closely to the precise definition of a Slice vs a Sliver. The current AM API methods imply that a sliver represents all resources at an aggregate for a given slice. However, this does not match the definition that previous GENI documents have used, nor the functionality that experimenters desire.
A sliver is the smallest set of resources at an aggregate that can be independently reserved and allocated. A given slice may contain multiple slivers at a single aggregate. A sliver may contain multiple components.
As such, the current AM API methods in fact operate on a group of slivers.
This change set would provide a means for experimenters to operate on individual slivers within their slice at a given aggregate, or perhaps to define and operate on arbitrary groups of slivers at a given aggregate.
Specifically, this change would provide ways to:
- Add resources to a slice at a given aggregate, where resources are already reserved - without having to delete and recreate the reservation at the aggregate. But for this capability, see the UpdateSliver proposal above.
- Delete specific resources (slivers) from a reservation at an aggregate, without losing other resources. For this capability, see the UpdateSliver proposal above. Alternatively, DeleteSliver could be modified to take either a
slice_urn
(as it does currently), or asliver_urn
, such as is returned in a manifest RSpec. - Renew the reservation on specific resources (slivers) within a reservation at an aggregate, while allowing other resource reservations to expire. However, it is unclear whether this particular function would be useful.
- Support fine grained manipulation of resources in other future AM API calls (such as StartSliver, StopSliver, RestartSliver). However, those other functions are not yet supported in the AM API.
Change Set E: Tickets
Note: This set of changes is not defined, currently under active discussion and has gotten no unofficial or official agreement.
The SFA defines the concept of a ticket. SFA1.0 section 5.3 says "A component signs an RSpec to produce a ticket, indicating a promise by the component to bind resources to the ticket-holder at some point in time." Tickets are promises to allocate resources.
Tickets are used in the ProtoGENI CMV2 interface, and are discussed on their wiki here. Tickets (and leases) are also used extensively in Orca. For details on the use of leases and tickets in Orca, see the Orca Book. However, each of these uses of the notion of tickets differs.
Tickets would enable a number of useful and possibly critical features:
- Brokers: 3rd parties consolidating, scheduling and allocating resources on behalf of a number of other aggregates
- Lending resources to other experimenters
- Coordinated or negotiated reservations: reserving resources from aggregate B only if aggregate A can give you a complementary resource. For example, a VLAN tag. This is related to stitching, both network stitching and the more general form.
- Two phase commit reservations (similar to the above)
- Scheduled reservations in the future
- Giving experimenters explicit control over when resources are started, stopped, and restarted (see the discussion on UpdateSliver above)
This change would introduce the concept of tickets, and new methods to use tickets. It requires:
- a ticket schema
- methods to get, redeem, split, and maybe return tickets
- semantics for what promises a ticket provides, and what it means to redeem and return tickets
- many other details.
Attachments (1)
- update-state.png (47.2 KB) - added by 12 years ago.
Download all attachments as: .zip