diff --git a/README.md b/README.md index 7278166..feadba4 100644 --- a/README.md +++ b/README.md @@ -64,13 +64,11 @@ Usage: chappe [command] Available Commands: - create Create chappe artifacts - get Get chappe artifacts + create Create chappe channel + get Get chappe message (via IPFS cid) help Help about any command publish Publish a private message to a channel - server Run a server subscribe Subscribe to a channel - update Print update instructions version Print the version Flags: @@ -79,19 +77,11 @@ Flags: Use "chappe [command] --help" for more information about a command. ``` -**PRs Welcome** - ## Usage -### Dependencies -#### IPFS -It's simple to run your own IPFS node using Docker with only these 3 commands, or you may use ```ipfs.digscar.com``` for light testing. -I run go-ipfs:latest running in Docker. -``` bash -export ipfs_staging= -export ipfs_data= +### Configuration File +Chappe will locate a file named ```config.yaml``` by looking in the following folders: ```.```, ```configs```, ```/etc/chappe```, and ```$HOME/.chappe```. -docker run -d --name ipfs_host -v $ipfs_staging:/export -v $ipfs_data:/data/ipfs -p 4001:4001 -p 127.0.0.1:8080:8080 -p 127.0.0.1:5001:5001 ipfs/go-ipfs:latest -``` +You can override any variable in the configuration file by setting an environment variable with a prefix of ```CHAPPE_```, followed by an all capital letter version of the variable that you want to override. ### Create a Key (Channel) ``` bash @@ -100,12 +90,17 @@ docker run -d --name ipfs_host -v $ipfs_staging:/export -v $ipfs_data:/data/ipfs The channel key is an assymetric RSA key. If you create a channel and you want another node to receive your messages, you would share the "chan4242.pem" file. ### Subscribe to the Channel -This runs a server, so fork your terminal shell to hold the ENV VARS intact. +This runs a server, so run it in a separate terminal. ``` bash ./chappe subscribe --channel-name chan4242 ``` -(After I publish, I will describe what happens with the subscribe process) +You can optionally request that the subscriber submit receipts/acknowledgements for each message. To prove that the receipient received and decrypted the message, the recipient's device key (unique to only that node) signs the decrypted message. This signature is posted to the blockchain, and the original sender may verify that the intended recipient(s) successfully received the message. + +To send a receipt, pass the ```send-receipts``` or ```-r``` flag. +``` bash +./chappe subscribe --channel-name chan424 -r +``` ### Publish to the Channel On a separate tab, publish a message: @@ -113,8 +108,7 @@ On a separate tab, publish a message: ./chappe publish --channel-name chan4242 --readable-memo "This is human-readable, unencrypted memo" ``` -Currently, the publish command generates fake private data to be shared on the channel. - +Currently, the publish command generates fake private data to be shared on the channel. More options will be added soon. For example: ``` json { @@ -133,102 +127,46 @@ For example: } ``` -#### Hybrid Encryption -In order to support large messages (files), we use hybrid encryption as described in this paper (https://pdfs.semanticscholar.org/87ff/ea85fbf52e22e4808e1fcc9e40ead4ff7738.pdf). - -We generate a random symmetric key to encrypt the message, then use the channel's (recipient's) assymetric public key to encrypt the symmetric key. - -```chappe``` handles all of this but the purpose of this is for documentation of how it works -##### Step 1: Generate a Random AES Key (Symmetric) - -Generate a one-time use key to encrypt the body of the message. -``` go -key := [32]byte{} -_, err := io.ReadFull(rand.Reader, key[:]) -if err != nil { - panic(err) -} -``` -##### Step 2: Encrypt the Message Data with the AES Key - -``` go -block, err := aes.NewCipher(key[:]) -if err != nil { - return nil, err -} - -gcm, err := cipher.NewGCM(block) -if err != nil { - return nil, err -} - -nonce := make([]byte, gcm.NonceSize()) -_, err = io.ReadFull(rand.Reader, nonce) -if err != nil { - return nil, err -} - -aesEncryptedData := gcm.Seal(nonce, nonce, plaintext, nil), nil -``` - -##### Step 3: Encrypt the AES Key with the Channel's Private Key -``` go -encryptedData, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, publicKey, key, label) -if err != nil { - fmt.Fprintf(os.Stderr, "Error from RSA encryption: %s\n", err) - return nil, err -} -``` - -##### Step 4: Publish Object to IPFS -The Encrypted Payload plus the Encrypted AES Key can be combined together, along with human-readable text to form the object. It is published to IPFS and a hash is returned. - -``` go -type PersistedObject struct { - EncryptedPayload []byte - EncryptedAESKey []byte - UnencryptedPayload string -} - -jsonPayloadNode, err := json.Marshal(payload) -if err != nil { - fmt.Fprintf(os.Stderr, "Could not marshal: %s", err) -} +The payload data is encrypted (see below) and constructed into an object and saved to IPFS. Here's an example of what one of the objects looks like: http://ipfs.digscar.com:8080/ipfs/QmNLuCqYR23RLzkE8fZvrnhsfaYJiawWAXcs2miLdeckND -hash, err := sh.Add(strings.NewReader(string(jsonPayloadNode))) -if err != nil { - fmt.Fprintf(os.Stderr, "Could not add data to IPFS: %s", err) +The blockchain transaction payload appears like this: +``` json +{ + "payload": [ + { + "key": "cid", + "value": "QmfBmT8CDSaRYQ6b7z1URNXZih7jWvgRdHw1oH5rQFAqoy" + }, + { + "key": "memo", + "value": "foobars memo" + } + ] } -fmt.Println("IPFS Hash: ", hash) ``` -##### Step 5: Publish IPFS Hash to EOSIO Blockchain -The user/node then publishes the IPFS hash to the appropriate blockchain, which records the event's existence, although elements of this metadata can be masked. -``` go -txOpts := &eos.TxOptions{} -if err := txOpts.FillFromChain(api); err != nil { - panic(fmt.Errorf("filling tx opts: %s", err)) -} - -tx := eos.NewTransaction([]*eos.Action{message.NewPub(hash, readableMemo)}, txOpts) -_, packedTx, err := api.SignTransaction(tx, txOpts.ChainID, eos.CompressionNone) -if err != nil { - panic(fmt.Errorf("sign transaction: %s", err)) -} +#### Hybrid Encryption +In order to support large messages (files), we use hybrid encryption as described in this paper (https://pdfs.semanticscholar.org/87ff/ea85fbf52e22e4808e1fcc9e40ead4ff7738.pdf). -response, err := api.PushTransaction(packedTx) -if err != nil { - panic(fmt.Errorf("push transaction: %s", err)) -} -``` +We generate a random symmetric key for each message, then use the channel's (recipient's) assymetric public key to encrypt the symmetric key. -### Back to Subscription +```chappe``` handles all of this but the purpose of this is for documentation of how it works +1. Generate a Random AES Key (Symmetric) +2. Encrypt the Message Data with the AES Key +3. Encrypt the AES Key with the Channel's Private Key +4. Publish Message to IPFS +5. Publish IPFS CID (hash) to EOSIO Blockchain -The inverse happens on the subscription side: -- dfuse fires a websocket ( TODO: [ ] need to migrate to GraphQL) -- IPFS document is retrieved -- AES key is decrypted -- Message is decrypted +### Dependencies +#### Dfuse +You'll need a dfuse API key. You can register for a free one at dfuse.io +#### IPFS +It's simple to run your own IPFS node using Docker with only these 3 commands, or you may use ```ipfs.digscar.com``` for light testing. +I run go-ipfs:latest running in Docker. +``` bash +export ipfs_staging= +export ipfs_data= -(TODO: need to add an signed acknowledgement back to the sender) \ No newline at end of file +docker run -d --name ipfs_host -v $ipfs_staging:/export -v $ipfs_data:/data/ipfs -p 4001:4001 -p 127.0.0.1:8080:8080 -p 127.0.0.1:5001:5001 ipfs/go-ipfs:latest +``` \ No newline at end of file diff --git a/cmd/create.go b/cmd/create.go index 107e529..d5fd693 100644 --- a/cmd/create.go +++ b/cmd/create.go @@ -28,11 +28,7 @@ func MakeCreate() *cobra.Command { encryption.CreateChannel(channelName) - log.Println( - `======================================================================= -key ` + channelName + ` created in files ` + channelName + `.pem (private) and ` + channelName + `.pub (public) -=======================================================================`) - + log.Println(`Channel files created: ` + channelName + `.pem (private key) and ` + channelName + `.pub (public key)`) return nil } return command diff --git a/cmd/publish.go b/cmd/publish.go index ffc835c..29f7a84 100644 --- a/cmd/publish.go +++ b/cmd/publish.go @@ -21,19 +21,17 @@ func MakePublish() *cobra.Command { var command = &cobra.Command{ Use: "publish", Short: "Publish a private message to a channel", - Long: `Create and share private messages with other nodes on a chappe network.`, - Example: ` chappe publish - chappe publish --channel-name MyChannel --readable-memo "This memo is not encrypted" - chappe publish --encrypt false`, - + Long: `Create and share private messages with other nodes on a chappe network. + Currently, only a randomly generated JSON object is sent as the + message body. Other options will be added shortly.`, + Example: `chappe publish --channel-name MyChannel --memo "This memo is not encrypted"`, SilenceUsage: false, } var channelName, readableMemo string var encryptFlag bool - command.Flags().StringVarP(&channelName, "channel-name", "n", "", "channel name") - command.Flags().StringVarP(&readableMemo, "readable-memo", "m", "", "Human readable memo to attach to payload (never encrypted)") + command.Flags().StringVarP(&readableMemo, "memo", "m", "", "Human readable memo to attach to payload (never encrypted)") command.Flags().BoolVarP(&encryptFlag, "encrypt", "", true, "Boolean flag whether to encrypt payload - defaults to true") command.RunE = func(command *cobra.Command, args []string) error { diff --git a/cmd/update.go b/cmd/update.go index 412cbc5..8cae13f 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -17,7 +17,6 @@ func MakeUpdate() *cobra.Command { command.Run = func(cmd *cobra.Command, args []string) { fmt.Println("Subscribe action is not yet implemented") fmt.Println("Contribute: https://github.com/eosio-enterprise/chappe/blob/master/CONTRIBUTING.md") - } return command } diff --git a/configs/example-config.yaml b/configs/example-config.yaml index e2ef769..a88e4a7 100644 --- a/configs/example-config.yaml +++ b/configs/example-config.yaml @@ -1,14 +1,19 @@ IPFS: - Endpoint: ec2-3-232-158-110.compute-1.amazonaws.com:5001 + Endpoint: ipfs.digscar.com:5001 Eosio: Endpoint: https://kylin.eosusa.news PublishAccount: messengerbus PublishPrivateKey: 5KAP1zytghuvowgprSPLNasajibZcxf4KMgdgNbrNj98xhcGAUa Dfuse: - Protocol: GraphQL # WebSocket will use WSEndpoint; else it defaults to GraphQL - WSEndpoint: wss://kylin.eos.dfuse.io/v1/stream + Protocol: GraphQL # only GraphQL supported now # WebSocket will use WSEndpoint; else it defaults to GraphQL + WSEndpoint: wss://kylin.eos.dfuse.io/v1/stream # only GraphQL supported now Origin: github.com/eosio-enterprise/chappe ApiKey: <> GraphQLEndpoint: kylin.eos.dfuse.io:443 KeyDirectory: channels/ -PublishInterval: 5s # Go Duration object \ No newline at end of file +PublishInterval: 5s # Go Duration object +DeviceRSAPrivateKey: mykey # uniquely represents the device (used for receipts) + +# coming soon +RevealMessage: true +RevealDelay: 60s # Time to wait before revealing the message \ No newline at end of file diff --git a/contracts/messenger/include/messenger.hpp b/contracts/messenger/include/messenger.hpp index fa5ec2d..1138219 100644 --- a/contracts/messenger/include/messenger.hpp +++ b/contracts/messenger/include/messenger.hpp @@ -7,7 +7,7 @@ CONTRACT messenger : public contract { using contract::contract; ACTION pub( string ipfs_hash, string memo ); - ACTION pubmap ( std::map payload); - using pub_action = action_wrapper<"pub"_n, &messenger::pub>; + // ACTION pubbytesmap ( std::map payload); + }; \ No newline at end of file diff --git a/contracts/messenger/src/messenger.cpp b/contracts/messenger/src/messenger.cpp index 6d05e16..c4407cc 100644 --- a/contracts/messenger/src/messenger.cpp +++ b/contracts/messenger/src/messenger.cpp @@ -1,3 +1,4 @@ #include ACTION messenger::pub( string ipfs_hash, string memo) {} -ACTION messenger::pubmap ( std::map payload) {} \ No newline at end of file +ACTION messenger::pubmap ( std::map payload) {} +// ACTION messenger::pubbytesmap ( std::map payload) {} \ No newline at end of file diff --git a/go.mod b/go.mod index 50c5685..645a368 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.13 require ( github.com/bxcodec/faker v2.0.1+incompatible github.com/dfuse-io/eosws-go v0.0.0-20191011181529-0eb3d4ce8743 - github.com/eoscanada/eos-go v0.9.0 + github.com/eoscanada/eos-go v0.9.1-0.20200316040626-bf09fb15dea8 github.com/golang/protobuf v1.3.3 github.com/ipfs/go-ipfs-api v0.0.3 github.com/multiformats/go-multihash v0.0.10 // indirect diff --git a/go.sum b/go.sum index 37e6de4..d0a8b19 100644 --- a/go.sum +++ b/go.sum @@ -73,8 +73,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/eoscanada/eos-go v0.8.5/go.mod h1:RKrm2XzZEZWxSMTRqH5QOyJ1fb/qKEjs2ix1aQl0sk4= -github.com/eoscanada/eos-go v0.9.0 h1:8Ko4/6lwn3KwbbDuaUB3p02OzbQVZVdxbp6noPChIkc= -github.com/eoscanada/eos-go v0.9.0/go.mod h1:6RuJFiRU1figWZ39M33o2cERU2MdL6VllElYLHTZNeo= +github.com/eoscanada/eos-go v0.9.1-0.20200316040626-bf09fb15dea8 h1:E79CwwnFq70bWq52l7qthwR2uY1EpVSUUojwUVbEgLs= +github.com/eoscanada/eos-go v0.9.1-0.20200316040626-bf09fb15dea8/go.mod h1:6RuJFiRU1figWZ39M33o2cERU2MdL6VllElYLHTZNeo= github.com/ethereum/go-ethereum v1.9.9/go.mod h1:a9TqabFudpDu1nucId+k9S8R9whYaHnGBLKFouA5EAo= github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= diff --git a/main.go b/main.go index 6d61ef3..375236e 100644 --- a/main.go +++ b/main.go @@ -25,11 +25,18 @@ func main() { }, } - var configFile string - rootCmd.Flags().StringVarP(&configFile, "config-file", "c", "configs/config.yaml", "Path/name of configuration file") - viper.SetConfigFile(configFile) //"configs/config.yaml") - if err := viper.ReadInConfig(); err != nil { - log.Fatalf("config file not found: %s", err) + viper.SetConfigName("config") + viper.SetConfigType("yaml") + viper.AddConfigPath("./configs") + viper.AddConfigPath("/etc/chappe/") + viper.AddConfigPath("$HOME/.chappe") + viper.AddConfigPath(".") + viper.SetEnvPrefix("CHAPPE") + viper.AutomaticEnv() + + err := viper.ReadInConfig() + if err != nil { + log.Fatalf("Fatal error config file: %s \n", err) } rootCmd.AddCommand(cmdCreate) diff --git a/pkg/dfuse-graphql.go b/pkg/dfuse-graphql.go index a7783a2..ac8d7d1 100644 --- a/pkg/dfuse-graphql.go +++ b/pkg/dfuse-graphql.go @@ -66,7 +66,7 @@ func createClient(endpoint string) pb.GraphQLClient { // TODO: need to replace messengerbus with viper.GetString("Eosio.PublishAccount") const operationEOS = `subscription { - searchTransactionsForward(query:"receiver:messengerbus action:pub") { + searchTransactionsForward(query:"receiver:messengerbus action:pubmap") { undo cursor trace { id matchingActions { json } } } @@ -117,14 +117,21 @@ func StreamMessages(ctx context.Context, channelName string, sendReceipts bool) result := document.SearchTransactionsForward if result.Undo { - log.Println("EOSIO transaction has been reverted, halting process. Skipping.") + log.Println("EOSIO transaction has been reverted, halting process. Skipping") + continue } else { for _, action := range result.Trace.MatchingActions { - data := action.JSON - if data["memo"] == "receipt" { + data := action.JSON["payload"].([]interface{}) + payload := make(map[string]string) + for i := 0; i < len(data); i++ { + imap := data[i].(map[string]interface{}) + payload[imap["key"].(string)] = imap["value"].(string) + } + + if payload["message_type"] == "receipt" { log.Println("Received receipt, ignoring.") } else { - message, err := receiveGQL(channelName, data) + message, err := receiveGQL(channelName, payload) if err == nil && sendReceipts { SendReceipt(channelName, message) } @@ -134,15 +141,19 @@ func StreamMessages(ctx context.Context, channelName string, sendReceipts bool) } } -func receiveGQL(channelName string, data map[string]interface{}) (Message, error) { - ipfsHash := data["ipfs_hash"] - memo := data["memo"] - log.Println("Received notification of new message: ", ipfsHash, "; memo: ", memo) - - msg, err := Load(channelName, ipfsHash.(string)) - if err != nil { - log.Println("Error loading message: ", err) - return msg, err +func receiveGQL(channelName string, payload map[string]string) (Message, error) { + // log.Println(payload) + var msg Message + cid, cidExists := payload["cid"] + if cidExists { + log.Println("Received notification of new message: ", payload["cid"], "; memo: ", payload["memo"]) + msg, err := Load(channelName, cid) + if err != nil { + log.Println("Error loading message: ", err) + return msg, err + } + return msg, nil } + log.Println("Message does not contain a CID, discarding.") return msg, nil } diff --git a/pkg/message.go b/pkg/message.go index b9236f2..7608cf0 100644 --- a/pkg/message.go +++ b/pkg/message.go @@ -13,9 +13,6 @@ import ( // Message ... type Message struct { - // EncryptedPayload []byte - // EncryptedAESKey []byte - // ReadableMemos []string Payload map[string][]byte } diff --git a/pkg/publish.go b/pkg/publish.go index 36046c6..15fca4f 100644 --- a/pkg/publish.go +++ b/pkg/publish.go @@ -1,6 +1,7 @@ package pkg import ( + "context" "encoding/hex" "encoding/json" "log" @@ -12,19 +13,19 @@ import ( "github.com/spf13/viper" ) -func newPub(ipfsHash, memo string) *eos.Action { - return &eos.Action{ - Account: eos.AN(viper.GetString("Eosio.PublishAccount")), - Name: eos.ActN("pub"), - Authorization: []eos.PermissionLevel{ - {Actor: eos.AN(viper.GetString("Eosio.PublishAccount")), Permission: eos.PN("active")}, - }, - ActionData: eos.NewActionData(PubActionPayload{ - IpfsHash: ipfsHash, - Memo: memo, - }), - } -} +// func newPub(ipfsHash, memo string) *eos.Action { +// return &eos.Action{ +// Account: eos.AN(viper.GetString("Eosio.PublishAccount")), +// Name: eos.ActN("pub"), +// Authorization: []eos.PermissionLevel{ +// {Actor: eos.AN(viper.GetString("Eosio.PublishAccount")), Permission: eos.PN("active")}, +// }, +// ActionData: eos.NewActionData(PubActionPayload{ +// IpfsHash: ipfsHash, +// Memo: memo, +// }), +// } +// } // PubMapActionPayload ... type PubMapActionPayload struct { @@ -44,37 +45,38 @@ func newPubMap(payload map[string]string) *eos.Action { } } -// PubActionPayload ... -type PubActionPayload struct { - IpfsHash string `json:"ipfs_hash"` - Memo string `json:"memo"` -} +// // PubActionPayload ... +// type PubActionPayload struct { +// IpfsHash string `json:"ipfs_hash"` +// Memo string `json:"memo"` +// } // PublishMapToBlockchain ... func PublishMapToBlockchain(payload map[string]string) (string, error) { + ctx := context.Background() api := eos.New(viper.GetString("Eosio.Endpoint")) keyBag := &eos.KeyBag{} - err := keyBag.ImportPrivateKey(viper.GetString("Eosio.PublishPrivateKey")) + err := keyBag.ImportPrivateKey(ctx, viper.GetString("Eosio.PublishPrivateKey")) if err != nil { log.Panicf("import private key: %s", err) } api.SetSigner(keyBag) txOpts := &eos.TxOptions{} - if err := txOpts.FillFromChain(api); err != nil { + if err := txOpts.FillFromChain(ctx, api); err != nil { log.Printf("Error filling tx opts: %s", err) return "error", err } tx := eos.NewTransaction([]*eos.Action{newPubMap(payload)}, txOpts) - _, packedTx, err := api.SignTransaction(tx, txOpts.ChainID, eos.CompressionNone) + _, packedTx, err := api.SignTransaction(ctx, tx, txOpts.ChainID, eos.CompressionNone) if err != nil { log.Printf("Error signing transaction: %s", err) return "error", err } - response, err := api.PushTransaction(packedTx) + response, err := api.PushTransaction(ctx, packedTx) if err != nil { log.Printf("Error pushing transaction: %s", err) return "error", err @@ -82,37 +84,38 @@ func PublishMapToBlockchain(payload map[string]string) (string, error) { return hex.EncodeToString(response.Processed.ID), nil } -// AddToEosio ... -func AddToEosio(cid string, readableMemo string) (string, error) { - api := eos.New(viper.GetString("Eosio.Endpoint")) - - keyBag := &eos.KeyBag{} - err := keyBag.ImportPrivateKey(viper.GetString("Eosio.PublishPrivateKey")) - if err != nil { - log.Panicf("import private key: %s", err) - } - api.SetSigner(keyBag) - - txOpts := &eos.TxOptions{} - if err := txOpts.FillFromChain(api); err != nil { - log.Printf("Error filling tx opts: %s", err) - return "error", err - } - - tx := eos.NewTransaction([]*eos.Action{newPub(cid, readableMemo)}, txOpts) - _, packedTx, err := api.SignTransaction(tx, txOpts.ChainID, eos.CompressionNone) - if err != nil { - log.Printf("Error signing transaction: %s", err) - return "error", err - } - - response, err := api.PushTransaction(packedTx) - if err != nil { - log.Printf("Error pushing transaction: %s", err) - return "error", err - } - return hex.EncodeToString(response.Processed.ID), nil -} +// // AddToEosio ... +// func AddToEosio(cid string, readableMemo string) (string, error) { +// ctx := context.Background() +// api := eos.New(viper.GetString("Eosio.Endpoint")) + +// keyBag := &eos.KeyBag{} +// err := keyBag.ImportPrivateKey(ctx, viper.GetString("Eosio.PublishPrivateKey")) +// if err != nil { +// log.Panicf("import private key: %s", err) +// } +// api.SetSigner(keyBag) + +// txOpts := &eos.TxOptions{} +// if err := txOpts.FillFromChain(ctx, api); err != nil { +// log.Printf("Error filling tx opts: %s", err) +// return "error", err +// } + +// tx := eos.NewTransaction([]*eos.Action{newPub(cid, readableMemo)}, txOpts) +// _, packedTx, err := api.SignTransaction(ctx, tx, txOpts.ChainID, eos.CompressionNone) +// if err != nil { +// log.Printf("Error signing transaction: %s", err) +// return "error", err +// } + +// response, err := api.PushTransaction(ctx, packedTx) +// if err != nil { +// log.Printf("Error pushing transaction: %s", err) +// return "error", err +// } +// return hex.EncodeToString(response.Processed.ID), nil +// } func addToIpfs(payload Message) string { sh := shell.NewShell(viper.GetString("IPFS.Endpoint")) @@ -131,12 +134,13 @@ func addToIpfs(payload Message) string { // Publish ... func Publish(payload Message) (string, error) { - var blockchainMemo string - memoBytes, memoExists := payload.Payload["BlockchainMemo"] + blockchainMemo, memoExists := payload.Payload["BlockchainMemo"] if !memoExists { - blockchainMemo = string("") - } else { - blockchainMemo = string(memoBytes) + blockchainMemo = []byte("") } - return AddToEosio(addToIpfs(payload), blockchainMemo) + + eosioPayload := make(map[string]string) + eosioPayload["cid"] = addToIpfs(payload) + eosioPayload["memo"] = string(blockchainMemo) + return PublishMapToBlockchain(eosioPayload) } diff --git a/pkg/receipt.go b/pkg/receipt.go index 57fa755..9efdf29 100644 --- a/pkg/receipt.go +++ b/pkg/receipt.go @@ -18,13 +18,13 @@ func SendReceipt(channelName string, msg Message) error { receiptStr := hex.EncodeToString(receiptSignature) log.Println("Sending receipt: ", receiptStr) - // receiptMap := make(map[string]string) - // receiptMap["receipt"] = receiptStr + receiptMap := make(map[string]string) + receiptMap["receipt"] = receiptStr + receiptMap["message_type"] = "receipt" - // trxID, _ := PublishMapToBlockchain(receiptMap) - // // currently, receipts will reveal other parties on the channel - // // TODO: mask metadata on receipts - trxID, _ := AddToEosio(receiptStr, "receipt") + // currently, receipts will reveal other parties on the channel + // TODO: mask metadata on receipts + trxID, _ := PublishMapToBlockchain(receiptMap) log.Println("Sent receipt, transaction ID: ", trxID) return nil