 
  The karma module provides a way to limit Transactions. Users are limited in the number and timing of transactions by various karma parameters. There is one user called the Oracle who has unlimited access.
Installation
To install, include the karma contract in the genesis.json file when starting the chain for the first time.
     {
            "vm": "plugin",
            "format": "plugin",
            "name": "karma",
            "location": "karma:1.0.0",
            "init": {
            }
     }
Activation and loom.yaml
Activating the karma functionality is done from the loom.yaml configuration file.
- KarmaEnabled boolFlag that sets the karma module on or off.
- KarmaSessionDuration int64A Time period in seconds. Karma restricts users to a configurable number of transactions during any interval of- SessionDurationseconds.
- KarmaMaxCallCount int64Base value used to calculate number of call Transaction permitted per- SessionDuration. A- KarmaMaxCallCount int64of- 0indicates there are no limit imposed on call transactions number.
- KarmaMaxDeployCount int64Base value used to calculate number of deploy Transaction permitted per- SessionDuration. A- KarmaMaxDeployCount int64of- 0indicates there are no limit imposed on deploy transactions number. Example loom.yaml fragment.
KarmaEnabled: true
KarmaSessionDuration: 60
KarmaMaxCallCount: 10
KarmaMaxDeployCount: 5
Accessing karma methods
Public karma methods can either be run either directly in code using one of the SDKs or from the command line the using loom executable.
$ ./loom karma --help
call a method of karma
Usage:
  loom karma [command]
Available Commands:
  append-sources-for-user add new source of karma to a user, requires oracle verification
  delete-sources-for-user delete sources assigned to user, requires oracle verification
  get-sources             list the karma sources
  get-total               calculate total karma for user
  get-user-state          list the karma sources for user
  reset-sources           reset the sources, requires oracle verification
  update-oracle           change the oracle or set initial oracle
Flags:
  -a, --address string   address file
      --chain string     chain ID (default "default")
  -h, --help             help for karma
  -k, --key string       private key file
  -r, --read string      URI for quering app state (default "http://localhost:46658/query")
  -w, --write string     URI for sending txs (default "http://localhost:46658/rpc")
Use "loom karma [command] --help" for more information about a command.
Oracle
- It is defined in the genesis file, and can be updated by the karma method UpdateOracle.
- It is unaffected by karma restrictions.
- To successfully call the following karma configuration transactions it is necessary to reference the oracle.
- AppendSourcesForUser
- DeleteSourcesForUser
- ResetSources
- UpdateOracleIf no oracle has been set yet then anyone can call- UpdateOracle, If an oracle has been set it is necssary to know the old oracle to change the oracle with- UpdateOracle.
 
Example genesis file entry.
    {
        "vm": "plugin",
        "format": "plugin",
        "name": "karma",
        "location": "karma:1.0.0",
        "init": {
                "Oracle": {
                    "chainId": "default",
                    "local": "QjWhaN9qvpdI9MjS1YuL1GukwLc="
                }
        }
    }
loom karma update-oracle
The oracle can be updated using the loom update-oracle command, which uses the UpdateOracle karma method
$ loom karma update-oracle --help
change the oracle
Usage:
  loom karma update-oracle (new oracle) [old oracle] [flags]
Flags:
  -h, --help   help for update-oracle
Global Flags:
  -a, --address string   address file
      --chain string     chain ID (default "default")
  -k, --key string       private key file
  -r, --read string      URI for quering app state (default "http://localhost:46658/query")
  -w, --write string     URI for sending txs (default "http://localhost:46658/rpc")
Changes the oracle from old oracle to new oracle.
For example if default:0xDeffe041cC978a193fCf0CE18b43b25B4592FC90 is the current oracle
$ karma update-oracle   default:0xAfaA41C81A316111fB0A4644B7a276c26bEA2C9F default:0xDeffe041cC978a193fCf0CE18b43b25B4592FC90  -k ./cmd/loom/data/pri
oracle changed
The old oracle can be omitted if no oracle has been set yet.
Sources
Karma is generated by sources. Sources could correspond to different user types, privilege levels, promotions or temporary changes in status.
type KarmaSourceReward struct {
    Name   string
    Reward int64
}
Nameis a descriptive string used to identify a source. Rewardis used to multiply karma associated with the source. A high Reward value means each point of karma generated by the source has more effect than a source with a lower Reward.
Sources can be configured in the genesis file or later by calling the karma GetSources and ResetSources methods.
Sources: Genesis File
Sources can be set up in the karma init segment of the DAppChain genesis file. This allows sources to be available the first time the DAppChain is run. For example:
    {
        "vm": "plugin",
        "format": "plugin",
        "name": "karma",
        "location": "karma:1.0.0",
        "init": {
            "Params": {
                "sources": [
                    {
                        "name": "sms",
                        "reward": "1"
                    },
                    {
                        "name": "oauth",
                        "reward": "3"
                    },
                    {
                        "name": "token",
                        "reward": "4"
                    }
                ]
            }
        }
    }
This starts the DAppChain with three sources, "sms", "oauth" and "token" with varying reward levels.
Sources: ResetSources
The karma method ResetSources is used to reset the karma parameters including the sources in a running DAppChain. You might want to download the existing parameters with GetSources and amend that before using to set the karma configuration parameters with UpdateConfig.
loom karma get-sources
Use the get-sources loom command to list karma sources using the GetSources karma method.
$ loom karma get-sources --help
list the karma sources
Usage:
  loom karma get-sources [flags]
Flags:
  -h, --help   help for get-sources
Global Flags:
  -a, --address string   address file
      --chain string     chain ID (default "default")
  -k, --key string       private key file
  -r, --read string      URI for quering app state (default "http://localhost:46658/query")
  -w, --write string     URI for sending txs (default "http://localhost:46658/rpc")
Process finished with exit code 0
For example
$ loom karma get-sources
{
  "sources": [
    {
      "name": "sms",
      "reward": "1"
    },
    {
      "name": "oauth",
      "reward": "3"
    },
    {
      "name": "token",
      "reward": "4"
    }
  ]
}
loom karma reset-sources
The sources can be reset using the ResetSources karma method reached via the loom karma update-sources command. If you want to add to existing sources will might want to use loom karma get-sources to get those existing sources.
$ loom karma reset-sources --help
reset the sources
Usage:
  loom karma reset-sources (oracle) [ [source] [reward] ]... [flags]
Flags:
  -h, --help   help for update-sources
Global Flags:
  -a, --address string   address file
      --chain string     chain ID (default "default")
  -k, --key string       private key file
  -r, --read string      URI for quering app state (default "http://localhost:46658/query")
  -w, --write string     URI for sending txs (default "http://localhost:46658/rpc")
For example if default:0xDeffe041cC978a193fCf0CE18b43b25B4592FC90 has previous been set as the oracle.
$ loom karma reset-sources default:0xDeffe041cC978a193fCf0CE18b43b25B4592FC90 "oauth" 3 "token" 5 "test" 7
sources successfully updated
go-loom update sources
The following Go code fragment gives an example of how you might do this in Go using go-loom, error checking skipped for readability.
import `github.com/loomnetwork/go-loom/builtin/types/karma`
func AddSource(name string, reward int64, signer auth.Signer, oracle loom.Address, karmaContact client.Contract) {
    // Get the existing configuration parameters
    var resp karma.KarmaSources
    _, err := karmaContact.StaticCall("GetSources", oracle.MarshalPB(), oracle, &resp)
    // Add the new source
    var configVal karma.KarmaSourcesValidator
    configVal.Oracle = oracle.MarshalPB()
    configVal.Sources = append(resp.Sources, &karma.KarmaSourceReward {
            Name: name,
            Reward: reward,
    })
    // Update the source information on the DAppChain
    _, err = karmaContact.Call("ResetSources", &configVal, signer, nil)
}
Users
If karma has been enabled, each user will be restricted in the transactions they can call by their karma allocation. If karma is enabled the following restrictions apply.
Deploy transactions
A strictly positive karma is required to do any transactions.
If KarmaMaxDeployCount is zero then there is no limit, imposed here, on the rate of deploy transactions.
Otherwise users will only be able to run KarmaMaxDeployCount deploy transactions in any period of SessionDurationseconds.
Call transactions
A strictly positive karma is required to do any transactions.
If KarmaMaxCallCount is zero then there is no limit, imposed here,
on the rate of call transactions.
Otherwise users will only be able to run KarmaMaxCallCount + total karma call transactions in any period of SessionDurationseconds. Where total karma1 is calculated from the count of sources held by the user as described below.
#User Karma
Each user will be associated with zero or more sources. This list may contain both active sources, in karma's current list of sources, or inactive sources not currently in the list of current sources.
type KarmaSource struct {
    Name  string
    Count int64 
}
type KarmaAddressSource struct {
    User    *types.Address 
    Sources []*KarmaSource 
}
Name identifies a source and corresponds to the Name field in KarmaSourceReward above. Count the number of a particular source associated with the address. The karma source provides to a user is `
KarmaSource.Count*KarmaSourceReward.Reward
The total amount of karma is the sum of the karma from each active karma source associated with the user. The sources associated with a user can configured either in the genesis file or by the karma methods AppendSourcesForUser and DeleteSourcesForUser.
Users: Genesis File
Users can be associated with sources in the genesis file. This allows users to have karma available as soon a new DAppChain starts. For example:
        {
            "vm": "plugin",
            "format": "plugin",
            "name": "karma",
            "location": "karma:1.0.0",
            "init": {
                "Params": {
                    "sources": [
                        {
                            "name": "sms",
                            "reward": "1"
                        },
                        {
                            "name": "oauth",
                            "reward": "3"
                        },
                        {
                            "name": "token",
                            "reward": "4"
                        }
                    ],
                    "users": [
                        {
                            "user": {
                                "chainId": "default",
                                "local": "QjWhaN9qvpdI9MjS1YuL1GukwLc="
                            },
                            "sources": [
                                {
                                    "name": "oauth",
                                    "count": "10"
                                },
                                {
                                    "name": "token",
                                    "count": "3"
                                }
                            ]
                        }
                    ],
                }
            }
        }
This genesis file fragment will create three sources and give the user with local address QjWhaN9qvpdI9MjS1YuL1GukwLc 10 rewards from oauth and3 rewards from token. This user would than start with 10*3 + 3*4 = 42 karma.
Users: AppendSourcesForUser and DeleteSourcesForUser
In a running DAppChain we can add a source to a user with the karma method AppendSourcesForUser. We need a list of names of the new sources, plus a count of the number of rewards. Sources can be removed using DeleteSourcesForUser.
loom karma append-sources-for-user
New sources can be associated with a user using karma method AppendSourcesForUser, this can be accessed with the loom karma append-sources-for-user command.
$ ./loom karma append-sources-for-user  --help
add new source of karma to a user, requires oracle verification
Usage:
  loom karma append-sources-for-user (user) (oracle) [ [source] [count] ]... [flags]
Flags:
  -h, --help   help for append-sources-for-user
Global Flags:
  -a, --address string   address file
      --chain string     chain ID (default "default")
  -k, --key string       private key file
  -r, --read string      URI for quering app state (default "http://localhost:46658/query")
  -w, --write string     URI for sending txs (default "http://localhost:46658/rpc")
For example if default:0xDeffe041cC978a193fCf0CE18b43b25B4592FC90 is the oracle and default:0xAfaA41C81A316111fB0A4644B7a276c26bEA2C9F the user to which we want to add new sources.
$ ./loom karma append-sources-for-user default:0xAfaA41C81A316111fB0A4644B7a276c26bEA2C9F  default:0xDeffe041cC978a193fCf0CE18b43b25B4592FC90 "oauth" 4 "token" 3 -k ./cmd/loom/data/pri
sources successfully updated
loom karma delete-sources-for-user
Existing sources can be disassociated with a user using the karma method DeleteUsersForUser. For this you can use the loom karma delete-sources-for-user.
$ loom karma delete-sources-for-user --help
delete sources assigned to user, requires oracle verification
Usage:
  loom karma delete-sources-for-user (user) (oracle) [name]... [flags]
Flags:
  -h, --help   help for delete-sources-for-user
Global Flags:
  -a, --address string   address file
      --chain string     chain ID (default "default")
  -k, --key string       private key file
  -r, --read string      URI for quering app state (default "http://localhost:46658/query")
  -w, --write string     URI for sending txs (default "http://localhost:46658/rpc")
For example if default:0xDeffe041cC978a193fCf0CE18b43b25B4592FC90 is the oracle and default:0xAfaA41C81A316111fB0A4644B7a276c26bEA2C9F the user to which we want to remove sources.
$ ./loom karma delete-sources-for-user default:0xAfaA41C81A316111fB0A4644B7a276c26bEA2C9F  default:0xDeffe041cC978a193fCf0CE18b43b25B4592FC90 "oauth" "token" -k ./cmd/loom/data/pri
sources successfully deleted
loom karma get-user-state
To get the list of sources that have been associated with a user, you can use the loom command loom karma get-user-state.
$ loom karma get-user-state --help
list the karma sources for user
Usage:
  loom karma get-user-state (user address) [flags]
Flags:
  -h, --help   help for get-user-state
Global Flags:
  -a, --address string   address file
      --chain string     chain ID (default "default")
  -k, --key string       private key file
  -r, --read string      URI for quering app state (default "http://localhost:46658/query")
  -w, --write string     URI for sending txs (default "http://localhost:46658/rpc")
For example, if default:0xDeffe041cC978a193fCf0CE18b43b25B4592FC90 is the user you are curious about
./loom karma get-user-state default:0xDeffe041cC978a193fCf0CE18b43b25B4592FC90
Karma methods
The following methods can be called by anyone.
- GetSources(ctx contract.StaticContext, ko *types.Address) (*ktypes.KarmaSources, error)Returns the current karma configuration details. This includes the current sources.
- GetTotal(ctx contract.StaticContext, params *types.Address) (*karma.KarmaTotal, error)Returns the total amount of karma in the system. The sum of the karma for each user that has been associated with a source.
- GetUserState(ctx contract.StaticContext, user *types.Address) (*karma.KarmaState, error)Returns the sources and counts associated with a user.
Can only be called by referencing the oracle unless there is no oracle yet.
- UpdateOracle(ctx contract.Context, params *ktypes.KarmaNewOracleValidator) error
The following methods can only be called by referencing the oracle
- ResetSources(ctx contract.Context, kpo *ktypes.KarmaSourcesValidator) errorReset the list of possible sources.
- AppendSourcesForUser(ctx contract.Context, ksu *karma.KarmaStateUser) errorAssociate a collection of sources with counts with a user. See above for details.
- DeleteSourcesForUser(ctx contract.Context, ksu *karma.KarmaStateKeyUser) errorDisassociate a collection of sources with a user. See above for details.
Other methods
- Meta() (plugin.Meta, error)
- Init(ctx contract.Context, req *InitRequest) error
Genesis entries
An example genesis file entry is shown below. The Init block can be empty, which just installs the karma contact on the DAppChain. You can define an Oracle in the genesis file. If you don't you can still call the karma method UpdateOracle to create an initial Oracle. It is possible to initialise the karma contract with a list of karma sources. If you do this, you can also allocate a list of users to have allocated amounts of these sources.
        {
            "vm": "plugin",
            "format": "plugin",
            "name": "karma",
            "location": "karma:1.0.0",
            "init": {
                "Oracle": {
                    "chainId": "default",
                    "local": "QjWhaN9qvpdI9MjS1YuL1GukwLc="
                 },
                "sources": [
                    {
                        "name": "sms",
                        "reward": "1"
                    },
                    {
                        "name": "oauth",
                        "reward": "3"
                    },
                    {
                        "name": "token",
                        "reward": "4"
                    }
                ],
                "users": [
                    {
                        "user": {
                            "chainId": "default",
                            "local": "QjWhaN9qvpdI9MjS1YuL1GukwLc="
                        },
                        "sources": [
                            {
                                "name": "oauth",
                                "count": "10"
                            },
                            {
                                "name": "token",
                                "count": "3"
                            }
                        ]
                    }
                ]
            }
        }