├── .gitignore ├── LICENSE.md ├── Makefile ├── README.md ├── api └── envelope.proto ├── go.mod ├── go.sum └── pkg ├── golang └── envelope │ ├── base │ └── base.go │ ├── envelope.go │ ├── envelope_v0_test.go │ ├── envelope_v1_test.go │ ├── v0 │ ├── decryption.go │ ├── encryption.go │ ├── metanet.go │ ├── models.go │ ├── protobuf │ │ └── envelope.pb.go │ └── serialize.go │ └── v1 │ ├── models.go │ └── serialize.go ├── python └── envelope_pb2.py └── typescript └── v0 └── protobuf.js /.gitignore: -------------------------------------------------------------------------------- 1 | test* 2 | tmp* 3 | Thumbs.db 4 | dist 5 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | OPEN BITCOIN SV LICENSE FOR BSV SOLUTION 2 | 3 | Effective Date: August 1, 2019 4 | 5 | Copyright © 2019 Tokenized Group Pty Ltd. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction other than the conditions set out below, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | 1. Blockchain Limitation. The grant to deal provided above is restricted to dealing in the Software only for purposes relating to the Bitcoin SV blockchain. The Bitcoin SV blockchain is defined, for purposes of this license, as the Bitcoin chain containing block height #556767 with this hash: 000000000000000001d956714215d96ffc00e0afda4cd0a96c96f8d802b1662b. 10 | 11 | 2. Redistributions of all copies or substantial portions of the source code of the Software must retain the above copyright notice and above permission notice (with blockchain limitation), this list of conditions and the following disclaimer. 12 | 13 | 3. Redistributions of all copies or substantial portions of the object code of the Software must reproduce the above copyright notice and above permission notice (with blockchain limitation), this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 14 | 15 | 4. Any work to the extent consisting of the Software or modifications made thereto, must be licensed under this license to anyone who comes into possession of a copy. regardless of how such work is packaged. Each time such a work is conveyed to a recipient, the recipient automatically receives this license from the original licensors, to run, modify and otherwise deal with that work. 16 | 17 | 5. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 18 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER DEALINGS IN THE SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 19 | 20 | LICENSE APPLICABILITY 21 | 22 | This license applies to any person or entity that downloads, reproduces or obtains the Software on or after the Effective Date stated above. 23 | 24 | For any person or entity that downloaded, reproduced or obtained the Software before the Effective Date under the prior applicable license entitled “BCH Solution Open Source License,” nChain Holdings Limited hereby designates the Bitcoin SV blockchain (as defined above) to be the only version or fork of the Bitcoin Cash (“BCH”) blockchain on which dealing in the Software is permitted, as set forth in paragraph 1 of that prior license. Therefore, the Software may be used only on the Bitcoin SV blockchain and may not be used on any other chain. 25 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | all: tools dep test 4 | 5 | dep: 6 | go get ./... 7 | 8 | tools: 9 | go get golang.org/x/lint/golint 10 | go get golang.org/x/tools/cmd/goimports 11 | 12 | test: 13 | go test ./... 14 | 15 | format: 16 | goimports -w ./ 17 | 18 | protoc: 19 | protoc --proto_path=api --go_opt=paths=source_relative --go_out=pkg/golang/envelope/v0/protobuf --js_out=library=protobuf,binary:pkg/typescript/v0 api/envelope.proto --python_out=pkg/python 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Envelope System 2 | 3 | This repository provides common encoding system for wrapping data in Bitcoin OP_RETURN scripts. 4 | 5 | ## Envelope v1 6 | 7 | Envelope is designed to be as simple and light weight as possible. Envelope's main purpose is to identify and allow combining of encoding and data protocols within Bitcoin script. Multiple protocols can be specified, in order, to describe the order the protocols should be applied. 8 | 9 | For example, an Envelope could specify a signing protocol and then a base data protocol. This would mean that the signing protocol should be applied first, which would likely involve parsing out the signature and checking it. Then the data protocol would be used to parse the data fields and apply meaning to them. 10 | 11 | Envelope allows combining of independent protocols. This allows each protocol to be single purpose and as simple as possible. Attempting to combine signing, encryption, compression, and data protocols all in one is a mistake because then if just one falls short, or isn't accepted by the ecosystem, the entire protocol needs to be updated. If they are separate then each protocol can much more easily be updated or replaced by a better protocol. Plus developers can pick and choose the protocols that accomplish their goals most effectively without being locked into a specific set. 12 | 13 | ## Getting Started 14 | 15 | #### First, clone the GitHub repo. 16 | ``` 17 | # Create parent directory 18 | mkdir -p $GOPATH/src/github.com/tokenized 19 | # Go into parent directory 20 | cd $GOPATH/src/github.com/tokenized 21 | # Clone repository 22 | git clone https://github.com/tokenized/envelope.git 23 | ``` 24 | 25 | #### Navigate to the root directory and run `make`. 26 | ``` 27 | # Go into repository directory 28 | cd envelope 29 | # Build project 30 | make 31 | ``` 32 | 33 | ## Project Structure 34 | 35 | * `api` - Version 0 Protocol Buffer message definitions shared between languages. 36 | * `pkg/golang` - Go language implementation. 37 | * `pkg/typescript` - Incomplete Typescript language implementation. 38 | * `pkg/...` - Add new language implementations. 39 | 40 | ## Data Structure 41 | 42 | The data is encoded as an unspendable OP_RETURN Bitcoin locking (output) script. 43 | 44 | `OP_FALSE OP_RETURN` 45 | 46 | Ensures the output script is provably unspendable. 47 | 48 | `0x02 0xbd 0x01` 49 | 50 | Push data containing 2 bytes. 0xbd is the envelope protocol ID and 0x01 is the envelope version 1. 51 | 52 | `PUSH_OP Payload Protocol ID Count` 53 | 54 | Bitcoin script number specifying the number of push datas containing payload protocol IDs. 55 | 56 | `PUSH_OP Payload Protocol IDs` 57 | 58 | Specified number of push datas containing the protocol IDs that pertain to the payload. 59 | 60 | `PUSH_OP Payload Push Data Count` 61 | 62 | Bitcoin script number specifying the number of push datas that make up the payload. 63 | 64 | `PUSH_OP Payloads` 65 | 66 | Specified number of push datas containing the payload. 67 | 68 | ### Tokenized Usage 69 | 70 | The [Tokenized](https://tokenized.com) protocol uses envelope to wrap its messages. 71 | 72 | * The envelope protocol IDs for a Tokenized action are "TKN" or "test.TKN". 73 | * The paylod for a Tokenized action is made of 2 or 3 push datas. 74 | * The first payload push data is a Bitcoin script number specifying the version, which is currently zero. 75 | * The second payload push data contains the code specifying which type of Tokenized action is included. 76 | * If the Tokenized action data is not empty, or "zero value", then the third push data containst the [protobuf](https://developers.google.com/protocol-buffers/) encoded data containing fields predefined for the Tokenized action code. 77 | 78 | ``` 79 | contractOffer := actions.ContractOffer{ 80 | ContractName: "Tokenized First Contract", 81 | BodyOfAgreementType: 2, 82 | BodyOfAgreement: ..., 83 | GoverningLaw: "AUD", 84 | VotingSystems: ..., 85 | ContractAuthFlags: ..., 86 | ... 87 | } 88 | 89 | // Protobuf Encode 90 | payload, err := proto.Marshal(&contractOffer) 91 | if err != nil { 92 | return errors.Wrap(err, "Failed to serialize action") 93 | } 94 | 95 | // Create Envelope Version 1 Message 96 | message := v1.NewMessage([][]byte{"test.TKN"}, 97 | [][]byte{bitcoin.PushNumberScript(int64(0)), []byte(contractOffer.Code())}) 98 | 99 | if len(payload) > 0 { 100 | // Only add action payload if it isn't empty. 101 | message.AddPayload(payload) 102 | } 103 | 104 | // Convert Envelope Message to Bitcoin Output Script 105 | var buf bytes.Buffer 106 | err = message.Serialize(&buf) 107 | if err != nil { 108 | return errors.Wrap(err, "Failed to serialize action envelope") 109 | } 110 | outputScript := buf.Bytes() 111 | 112 | // Put output script in Bitcoin Tx Output as part of a Bitcoin transaction signed by the contract administrator, and addressed to the contract address. 113 | tx.AddTxOut(wire.NewTxOut(0, outputScript)) 114 | ``` 115 | 116 | ### File System Example Usage 117 | 118 | Envelope can be used to store files on chain. Keep in mind this is just an example. The exact specifics of a file storage protocol should be defined and shared before being used. We also recommend that when encrypting a file the file name and type be included in the encrypted payload instead of the Envelope header fields. 119 | 120 | * The envelope payload protocolID is "F". 121 | * The payload can contain 2 or 3 push datas. 122 | * The first payload is the file name. 123 | * The second payload is the MIME type of the file. 124 | * If the file is not empty then the third paylod contains the file data. If the file is empty then only 2 payloads are specified for the envelope. 125 | 126 | 127 | #### Public File 128 | ``` 129 | payload, err := ioutil.ReadFile("company_logo.png") 130 | if err != nil { 131 | return errors.Wrap(err, "Failed to read file") 132 | } 133 | 134 | // Create Envelope Version 1 Message 135 | message := v1.NewMessage([][]byte{"F"}, 136 | [][]byte{[]byte("company_logo.png"), []byte("image/png")}) 137 | 138 | if len(payload) > 0 { 139 | // Only add action payload if it isn't empty. 140 | message.AddPayload(payload) 141 | } 142 | 143 | // Convert Envelope Message to Bitcoin Output Script 144 | var buf bytes.Buffer 145 | err = message.Serialize(&buf) 146 | if err != nil { 147 | return errors.Wrap(err, "Failed to serialize envelope") 148 | } 149 | outputScript := buf.Bytes() 150 | 151 | // Put output script in Bitcoin Tx Output. 152 | tx.AddTxOut(wire.NewTxOut(0, outputScript)) 153 | ``` 154 | 155 | # License 156 | 157 | The Tokenized Envelope System is open-sourced software licensed under the [OPEN BITCOIN SV](LICENSE.md) license. 158 | -------------------------------------------------------------------------------- /api/envelope.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package="github.com/tokenized/envelope/pkg/golang/envelope/v0/protobuf"; 4 | 5 | package protobuf; 6 | 7 | message Envelope { 8 | uint64 Version = 1; // Protocol specific version 9 | bytes Type = 2; // Data type of payload. 10 | bytes Identifier = 3; // Protocol specific identifier for the payload (i.e. message type, data name) 11 | 12 | MetaNet MetaNet = 4; 13 | 14 | repeated EncryptedPayload EncryptedPayloads = 5; 15 | } 16 | 17 | message MetaNet { 18 | uint32 Index = 1; // The index of the input containing the public key. 19 | bytes Parent = 2; // The 32 byte txid of the parent. 20 | } 21 | 22 | message EncryptedPayload { 23 | uint32 Sender = 1; 24 | repeated Receiver Receivers = 2; 25 | bytes Payload = 3; 26 | uint32 EncryptionType = 4; 27 | } 28 | 29 | message Receiver { 30 | uint32 Index = 1; 31 | bytes EncryptedKey = 2; 32 | } 33 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tokenized/envelope 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/golang/protobuf v1.3.2 7 | github.com/pkg/errors v0.9.1 8 | github.com/tokenized/pkg v0.6.0 9 | ) 10 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= 2 | github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= 3 | github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= 4 | github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= 5 | github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= 6 | github.com/aws/aws-sdk-go v1.35.3 h1:r0puXncSaAfRt7Btml2swUo74Kao+vKhO3VLjwDjK54= 7 | github.com/aws/aws-sdk-go v1.35.3/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= 8 | github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= 9 | github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= 10 | github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= 11 | github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= 12 | github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= 13 | github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= 14 | github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= 15 | github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= 16 | github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= 17 | github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= 18 | github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= 19 | github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= 20 | github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= 21 | github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 22 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 23 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 24 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 25 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 26 | github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= 27 | github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= 28 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 29 | github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= 30 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 31 | github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= 32 | github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= 33 | github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 34 | github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 35 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 36 | github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 37 | github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= 38 | github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= 39 | github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= 40 | github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= 41 | github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= 42 | github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= 43 | github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= 44 | github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= 45 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 46 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 47 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 48 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 49 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 50 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 51 | github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 52 | github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 53 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 54 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 55 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 56 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 57 | github.com/scottjbarr/redis v0.0.1/go.mod h1:HIzxEkRRpIDMZHOU/iavqyd+uQeQwqQncXoYpqJdGgM= 58 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 59 | github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= 60 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 61 | github.com/tokenized/config v0.2.2 h1:dGfFdv3P6JK9TcHvud34vozocm3Qq2Wxbc9PRctgDL8= 62 | github.com/tokenized/config v0.2.2/go.mod h1:CfxdNBZh5W1CCmE4bKHrSq7dgKQiNUxdrDtmvhemq2w= 63 | github.com/tokenized/logger v0.1.3 h1:Vq/2jEgqyDfjJPgoMo773/bn7ZUow8EWSAY8+gFdTQI= 64 | github.com/tokenized/logger v0.1.3/go.mod h1:bA5PfUEFwtUy0yEIIq4Q3ZwBk1kIZTkYIRASq3fPw+k= 65 | github.com/tokenized/pkg v0.6.0 h1:NIClG9+CFK7r5Y1YckqfR1A4JGniRg7qn/F3RFoU2CY= 66 | github.com/tokenized/pkg v0.6.0/go.mod h1:reIXdZflcfFbuX1RvX90yAjlYVJaUiYDc5CWJ6qCQww= 67 | github.com/tokenized/threads v0.1.2/go.mod h1:+/44KAYA6wqU+AC743pLGBgzkD06IB9+piOOE8BkGK0= 68 | github.com/tyler-smith/go-bip32 v0.0.0-20170922074101-2c9cfd177564 h1:NXXyQVeRVLK8Xu27/hkkjwVOZLk5v4ZBEvvMtqMqznM= 69 | github.com/tyler-smith/go-bip32 v0.0.0-20170922074101-2c9cfd177564/go.mod h1:0/YuQQF676+d4CMNclTqGUam1EDwz0B8o03K9pQqA3c= 70 | golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 71 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 72 | golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 73 | golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 h1:cg5LA/zNPRzIXIWSCxQW10Rvpy94aQh3LT/ShoCpkHw= 74 | golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 75 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 76 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 77 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= 78 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 79 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 80 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 81 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 82 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 83 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 84 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 85 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 86 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 87 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 88 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 89 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 90 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 91 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 92 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 93 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 94 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= 95 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 96 | launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= 97 | launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= 98 | -------------------------------------------------------------------------------- /pkg/golang/envelope/base/base.go: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | import ( 4 | "bytes" 5 | "encoding/hex" 6 | "fmt" 7 | "strings" 8 | 9 | "github.com/tokenized/pkg/bitcoin" 10 | 11 | "github.com/pkg/errors" 12 | ) 13 | 14 | var ( 15 | // Known Protocol Identifiers 16 | ProtocolIDTokenized = ProtocolID("TKN") 17 | ProtocolIDTokenizedTest = ProtocolID("test.TKN") 18 | ProtocolIDFlag = ProtocolID("flag") 19 | ProtocolIDUUID = ProtocolID("uuid") // Protocol ID for Universally Unique IDentifiers 20 | ProtocolIDSignedMessages = ProtocolID("S") // Protocol ID for Channels signed messages 21 | ProtocolIDInvoices = ProtocolID("I") // Protocol ID for Channels invoice negotiation 22 | ProtocolIDMerkleProof = ProtocolID("MP") // Protocol ID for Channels merkle proofs 23 | ProtocolIDReject = ProtocolID("RJ") // Protocol ID for Channels reject messages 24 | ProtocolIDMessageID = ProtocolID("ID") // Protocol ID for Channels message ids 25 | ProtocolIDRelationships = ProtocolID("RS") // Protocol ID for Channels relationship messages 26 | ProtocolIDResponse = ProtocolID("RE") // Protocol ID for Channels response messages 27 | 28 | ErrNotEnvelope = errors.New("Not an envelope") 29 | ErrUnknownVersion = errors.New("Unknown version") 30 | ErrInvalidEnvelope = errors.New("Invalid Envelope") 31 | ) 32 | 33 | type ProtocolID bitcoin.Hex // Hex is just a byte slice that JSON marshals as hex 34 | type ProtocolIDs []ProtocolID 35 | 36 | type Data struct { 37 | ProtocolIDs ProtocolIDs 38 | Payload bitcoin.ScriptItems 39 | } 40 | 41 | // ParseHeader parses an Envelope header and returns the version. Returns ErrNotEnvelope if it is 42 | // not an Envelope. 43 | func ParseHeader(buf *bytes.Reader) (uint8, error) { 44 | // Header 45 | if buf.Len() < 5 { 46 | return 0, ErrNotEnvelope 47 | } 48 | 49 | var b byte 50 | var err error 51 | 52 | b, err = buf.ReadByte() 53 | if err != nil { 54 | return 0, errors.Wrap(err, "read op return") 55 | } 56 | 57 | if b != bitcoin.OP_RETURN { 58 | if b != bitcoin.OP_FALSE { 59 | return 0, ErrNotEnvelope 60 | } 61 | 62 | b, err = buf.ReadByte() 63 | if err != nil { 64 | return 0, errors.Wrap(err, "read op return") 65 | } 66 | 67 | if b != bitcoin.OP_RETURN { 68 | return 0, ErrNotEnvelope 69 | } 70 | } 71 | 72 | // Envelope Protocol ID 73 | _, protocolID, err := bitcoin.ParsePushDataScript(buf) 74 | if err != nil { 75 | return 0, errors.Wrap(err, "parse protocol ID") 76 | } 77 | if len(protocolID) != 2 { 78 | return 0, ErrNotEnvelope 79 | } 80 | if protocolID[0] != 0xbd { 81 | return 0, ErrNotEnvelope 82 | } 83 | 84 | return protocolID[1], nil 85 | } 86 | 87 | func (id ProtocolID) String() string { 88 | if isText(id) { 89 | return string(id) 90 | } 91 | 92 | return fmt.Sprintf("0x%s", hex.EncodeToString(id)) 93 | } 94 | 95 | func (ids ProtocolIDs) String() string { 96 | result := make([]string, len(ids)) 97 | for i, id := range ids { 98 | result[i] = id.String() 99 | } 100 | 101 | return strings.Join(result, ",") 102 | } 103 | 104 | // MarshalJSON converts to json. 105 | func (id ProtocolID) MarshalJSON() ([]byte, error) { 106 | return []byte(fmt.Sprintf("\"%s\"", id)), nil 107 | } 108 | 109 | // UnmarshalJSON converts from json. 110 | func (id *ProtocolID) UnmarshalJSON(data []byte) error { 111 | l := len(data) 112 | if l < 2 { 113 | return errors.New("Missing quotes") 114 | } 115 | if data[0] != '"' || data[l-1] != '"' { 116 | return errors.New("Missing quotes") 117 | } 118 | 119 | s := string(data[1 : l-1]) 120 | if strings.HasPrefix(s, "0x") { 121 | b, err := hex.DecodeString(s[2:]) 122 | if err != nil { 123 | return errors.Wrap(err, "hex") 124 | } 125 | 126 | *id = ProtocolID(b) 127 | return nil 128 | } 129 | 130 | *id = ProtocolID(data[1 : l-1]) 131 | return nil 132 | } 133 | 134 | // MarshalText returns the text encoding of the hash. 135 | // Implements encoding.TextMarshaler interface. 136 | func (id ProtocolID) MarshalText() ([]byte, error) { 137 | return []byte(id.String()), nil 138 | } 139 | 140 | // UnmarshalText parses a text encoded hash and sets the value of this object. 141 | // Implements encoding.TextUnmarshaler interface. 142 | func (id *ProtocolID) UnmarshalText(text []byte) error { 143 | s := string(text) 144 | if strings.HasPrefix(s, "0x") { 145 | b, err := hex.DecodeString(s[2:]) 146 | if err != nil { 147 | return errors.Wrap(err, "hex") 148 | } 149 | 150 | *id = ProtocolID(b) 151 | return nil 152 | } 153 | 154 | *id = ProtocolID(text) 155 | return nil 156 | } 157 | 158 | // MarshalBinary returns the binary encoding of the hash. 159 | // Implements encoding.BinaryMarshaler interface. 160 | func (id ProtocolID) MarshalBinary() ([]byte, error) { 161 | return id, nil 162 | } 163 | 164 | // UnmarshalBinary parses a binary encoded hash and sets the value of this object. 165 | // Implements encoding.BinaryUnmarshaler interface. 166 | func (id *ProtocolID) UnmarshalBinary(data []byte) error { 167 | *id = data 168 | return nil 169 | } 170 | 171 | func isText(bs []byte) bool { 172 | for _, b := range bs { 173 | if b < 0x20 { // ' ' space character 174 | return false 175 | } 176 | 177 | if b > 0x7e { // '~' tilde character 178 | return false 179 | } 180 | } 181 | 182 | return true 183 | } 184 | -------------------------------------------------------------------------------- /pkg/golang/envelope/envelope.go: -------------------------------------------------------------------------------- 1 | package envelope 2 | 3 | import ( 4 | "bytes" 5 | 6 | "github.com/tokenized/envelope/pkg/golang/envelope/base" 7 | v0 "github.com/tokenized/envelope/pkg/golang/envelope/v0" 8 | v1 "github.com/tokenized/envelope/pkg/golang/envelope/v1" 9 | "github.com/tokenized/pkg/bitcoin" 10 | 11 | "github.com/pkg/errors" 12 | ) 13 | 14 | type BaseMessage interface { 15 | EnvelopeVersion() uint8 // Envelope protocol version 16 | PayloadProtocols() base.ProtocolIDs // Protocol IDs of payloads. (recommended to be ascii text) 17 | 18 | PayloadCount() int 19 | PayloadAt(offset int) []byte 20 | 21 | // Serialize creates an OP_RETURN script in the "envelope" format containing the specified data. 22 | Serialize(buf *bytes.Buffer) error 23 | } 24 | 25 | // Deserialize reads the Message from an OP_RETURN script. 26 | func Deserialize(buf *bytes.Reader) (BaseMessage, error) { 27 | // Header 28 | if buf.Len() < 5 { 29 | return nil, base.ErrNotEnvelope 30 | } 31 | 32 | var b byte 33 | var err error 34 | 35 | b, err = buf.ReadByte() 36 | if err != nil { 37 | return nil, errors.Wrap(err, "read op return") 38 | } 39 | 40 | if b != bitcoin.OP_RETURN { 41 | if b != bitcoin.OP_FALSE { 42 | return nil, base.ErrNotEnvelope 43 | } 44 | 45 | b, err = buf.ReadByte() 46 | if err != nil { 47 | return nil, errors.Wrap(err, "read op return") 48 | } 49 | 50 | if b != bitcoin.OP_RETURN { 51 | return nil, base.ErrNotEnvelope 52 | } 53 | } 54 | 55 | // Envelope Protocol ID 56 | _, protocolID, err := bitcoin.ParsePushDataScript(buf) 57 | if err != nil { 58 | return nil, errors.Wrap(err, "parse protocol ID") 59 | } 60 | if len(protocolID) != 2 { 61 | return nil, base.ErrNotEnvelope 62 | } 63 | if protocolID[0] != 0xbd { 64 | return nil, base.ErrNotEnvelope 65 | } 66 | 67 | // Version 0 for backwards compatibility 68 | if protocolID[1] == 0 { 69 | return v0.Deserialize(buf) 70 | } 71 | 72 | if protocolID[1] != 1 { 73 | return nil, base.ErrUnknownVersion 74 | } 75 | 76 | // Version 1 77 | return v1.Deserialize(buf) 78 | } 79 | -------------------------------------------------------------------------------- /pkg/golang/envelope/envelope_v0_test.go: -------------------------------------------------------------------------------- 1 | package envelope 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | 7 | v0 "github.com/tokenized/envelope/pkg/golang/envelope/v0" 8 | "github.com/tokenized/envelope/pkg/golang/envelope/v0/protobuf" 9 | "github.com/tokenized/pkg/bitcoin" 10 | "github.com/tokenized/pkg/wire" 11 | 12 | "github.com/golang/protobuf/proto" 13 | ) 14 | 15 | var retentionTests = []struct { 16 | protocol []byte 17 | version uint64 18 | payloadType []byte 19 | identifier []byte 20 | payload []byte 21 | }{ 22 | { 23 | protocol: []byte("tokenized"), 24 | version: 1, 25 | payloadType: nil, 26 | identifier: nil, 27 | payload: []byte("Test data 1"), 28 | }, 29 | { 30 | protocol: []byte("test"), 31 | version: 1, 32 | payloadType: nil, 33 | identifier: nil, 34 | payload: []byte("5"), 35 | }, 36 | { 37 | protocol: []byte{0xbe, 0xef}, 38 | version: 1, 39 | payloadType: []byte("beef"), 40 | identifier: nil, 41 | payload: nil, 42 | }, 43 | { 44 | protocol: []byte{0xbe, 0xef}, 45 | version: 1, 46 | payloadType: nil, 47 | identifier: []byte("beef"), 48 | payload: nil, 49 | }, 50 | } 51 | 52 | func TestRetention(t *testing.T) { 53 | for i, test := range retentionTests { 54 | message := v0.NewMessage(test.protocol, test.version, test.payload) 55 | 56 | if len(test.payloadType) > 0 { 57 | message.SetPayloadType(test.payloadType) 58 | } 59 | if len(test.identifier) > 0 { 60 | message.SetPayloadIdentifier(test.identifier) 61 | } 62 | 63 | var buf bytes.Buffer 64 | err := message.Serialize(&buf) 65 | if err != nil { 66 | t.Fatalf("Test %d Failed Serialize : %s", i, err) 67 | } 68 | 69 | reader := bytes.NewReader(buf.Bytes()) 70 | readBase, err := Deserialize(reader) 71 | if err != nil { 72 | t.Fatalf("Test %d Failed Deserialize : %s", i, err) 73 | } 74 | 75 | read, ok := readBase.(*v0.Message) 76 | if !ok { 77 | t.Fatalf("Wrong message type") 78 | } 79 | 80 | if !bytes.Equal(test.protocol, read.PayloadProtocol()) { 81 | t.Fatalf("Test %d protocol wasn't retained : want 0x%x, got 0x%x", i+1, test.protocol, 82 | read.PayloadProtocol()) 83 | } 84 | if test.version != read.PayloadVersion() { 85 | t.Fatalf("Test %d version wasn't retained : want %d, got %d", i+1, test.version, 86 | read.PayloadVersion()) 87 | } 88 | if !bytes.Equal(test.payloadType, read.PayloadType()) { 89 | t.Fatalf("Test %d payload type wasn't retained : want 0x%x, got 0x%x", i+1, 90 | test.payloadType, read.PayloadType()) 91 | } 92 | if !bytes.Equal(test.identifier, read.PayloadIdentifier()) { 93 | t.Fatalf("Test %d identifier wasn't retained : want 0x%x, got 0x%x", i+1, 94 | test.identifier, read.PayloadIdentifier()) 95 | } 96 | if !bytes.Equal(test.payload, read.Payload()) { 97 | t.Fatalf("Test %d payload wasn't retained : want 0x%x, got 0x%x", i+1, test.payload, 98 | read.Payload()) 99 | } 100 | } 101 | } 102 | 103 | var encryptionTests = []struct { 104 | protocol []byte 105 | version uint64 106 | payload []byte 107 | encryptedPayload []byte 108 | }{ 109 | { 110 | protocol: []byte("tokenized"), 111 | version: 1, 112 | payload: []byte("Test data 1"), 113 | encryptedPayload: []byte("Encrypted Data 234"), // more than aes block size of 16 114 | }, 115 | { 116 | protocol: []byte("test"), 117 | version: 1, 118 | payload: []byte("5"), 119 | encryptedPayload: []byte(""), // empty 120 | }, 121 | { 122 | protocol: []byte{0xbe, 0xef}, 123 | version: 1, 124 | payload: nil, 125 | encryptedPayload: nil, 126 | }, 127 | { 128 | protocol: []byte{0xbe, 0xef}, 129 | version: 1, 130 | payload: nil, 131 | encryptedPayload: []byte("test"), // less than aes block size of 16 132 | }, 133 | { 134 | protocol: []byte{0xbe, 0xef}, 135 | version: 1, 136 | payload: nil, 137 | encryptedPayload: []byte("testtesttesttest"), // exactly block size 138 | }, 139 | { 140 | protocol: []byte{0xbe, 0xef}, 141 | version: 1, 142 | payload: nil, 143 | encryptedPayload: []byte{0xff}, 144 | }, 145 | { 146 | protocol: []byte{0xbe, 0xef}, 147 | version: 1, 148 | payload: nil, 149 | encryptedPayload: []byte{0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 150 | }, 151 | { 152 | protocol: []byte{0xbe, 0xef}, 153 | version: 1, 154 | payload: nil, 155 | encryptedPayload: []byte{0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}, 156 | }, 157 | { 158 | protocol: []byte{0xbe, 0xef}, 159 | version: 1, 160 | payload: nil, 161 | encryptedPayload: []byte{0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}, 162 | }, 163 | { 164 | protocol: []byte{0xbe, 0xef}, 165 | version: 1, 166 | payload: nil, 167 | encryptedPayload: []byte{0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00}, 168 | }, 169 | } 170 | 171 | func TestEncryptionNoReceiver(t *testing.T) { 172 | for i, test := range encryptionTests { 173 | message := v0.NewMessage(test.protocol, test.version, test.payload) 174 | sender, err := bitcoin.GenerateKey(bitcoin.TestNet) 175 | 176 | var fakeScriptBuf bytes.Buffer 177 | err = bitcoin.WritePushDataScript(&fakeScriptBuf, sender.PublicKey().Bytes()) 178 | if err != nil { 179 | t.Fatalf("Test %d add public key to script failed : %s", i+1, err) 180 | } 181 | err = bitcoin.WritePushDataScript(&fakeScriptBuf, []byte("fake signature")) 182 | if err != nil { 183 | t.Fatalf("Test %d add signature to script failed : %s", i+1, err) 184 | } 185 | 186 | tx := wire.NewMsgTx(2) 187 | if err = addFakeInput(tx, sender); err != nil { 188 | t.Fatalf("Test %d failed to add input : %s", i+1, err) 189 | } 190 | 191 | err = message.AddEncryptedPayload(test.encryptedPayload, tx, 0, sender, nil) 192 | if err != nil { 193 | t.Fatalf("Test %d add encrypted payload failed : %s", i+1, err) 194 | } 195 | 196 | var buf bytes.Buffer 197 | err = message.Serialize(&buf) 198 | if err != nil { 199 | t.Fatalf("Test %d failed serialize : %s", i, err) 200 | } 201 | 202 | reader := bytes.NewReader(buf.Bytes()) 203 | baseRead, err := Deserialize(reader) 204 | if err != nil { 205 | t.Fatalf("Test %d failed deserialize : %s", i, err) 206 | } 207 | read, ok := baseRead.(*v0.Message) 208 | if !ok { 209 | t.Fatalf("Test %d failed to convert read to v0 message", i+1) 210 | } 211 | 212 | if read.EncryptedPayloadCount() != 1 { 213 | t.Fatalf("Test %d wrong amount of encrypted payloads : %d", i, read.EncryptedPayloadCount()) 214 | } 215 | 216 | encryptedPayload := read.EncryptedPayload(0) 217 | encPayload, err := encryptedPayload.SenderDecrypt(tx, sender, bitcoin.PublicKey{}) 218 | if err != nil { 219 | t.Fatalf("Test %d failed decrypt : %s", i, err) 220 | } 221 | 222 | if !bytes.Equal(test.encryptedPayload, encPayload) { 223 | t.Fatalf("Test %d encrypted payload doesn't match :\nwant 0x%x\ngot 0x%x", i+1, 224 | test.encryptedPayload, encPayload) 225 | } 226 | } 227 | } 228 | 229 | func TestEncryptionSingleReceiver(t *testing.T) { 230 | for i, test := range encryptionTests { 231 | message := v0.NewMessage(test.protocol, test.version, test.payload) 232 | sender, err := bitcoin.GenerateKey(bitcoin.TestNet) 233 | receiver, err := bitcoin.GenerateKey(bitcoin.TestNet) 234 | 235 | tx := wire.NewMsgTx(2) 236 | if err = addFakeInput(tx, sender); err != nil { 237 | t.Fatalf("Test %d failed to add input : %s", i+1, err) 238 | } 239 | if err = addFakeOutput(tx, receiver); err != nil { 240 | t.Fatalf("Test %d failed to add output : %s", i+1, err) 241 | } 242 | 243 | err = message.AddEncryptedPayload(test.encryptedPayload, tx, 0, sender, 244 | []bitcoin.PublicKey{receiver.PublicKey()}) 245 | if err != nil { 246 | t.Fatalf("Test %d add encrypted payload failed : %s", i+1, err) 247 | } 248 | 249 | var buf bytes.Buffer 250 | err = message.Serialize(&buf) 251 | if err != nil { 252 | t.Fatalf("Test %d failed serialize : %s", i, err) 253 | } 254 | 255 | reader := bytes.NewReader(buf.Bytes()) 256 | baseRead, err := Deserialize(reader) 257 | if err != nil { 258 | t.Fatalf("Test %d failed deserialize : %s", i, err) 259 | } 260 | read, ok := baseRead.(*v0.Message) 261 | if !ok { 262 | t.Fatalf("Test %d failed to convert read to v0 message", i+1) 263 | } 264 | 265 | if read.EncryptedPayloadCount() != 1 { 266 | t.Fatalf("Test %d wrong amount of encrypted payloads : %d", i, read.EncryptedPayloadCount()) 267 | } 268 | 269 | encryptedPayload := read.EncryptedPayload(0) 270 | encPayload, err := encryptedPayload.SenderDecrypt(tx, sender, receiver.PublicKey()) 271 | if err != nil { 272 | t.Fatalf("Test %d failed decrypt : %s", i, err) 273 | } 274 | 275 | if !bytes.Equal(test.encryptedPayload, encPayload) { 276 | t.Fatalf("Test %d encrypted payload doesn't match :\nwant 0x%x\ngot 0x%x", i+1, 277 | test.encryptedPayload, encPayload) 278 | } 279 | } 280 | } 281 | 282 | func TestEncryptionMultiReceiver(t *testing.T) { 283 | for i, test := range encryptionTests { 284 | message := v0.NewMessage(test.protocol, test.version, test.payload) 285 | sender, err := bitcoin.GenerateKey(bitcoin.TestNet) 286 | receiver1, err := bitcoin.GenerateKey(bitcoin.TestNet) 287 | receiver2, err := bitcoin.GenerateKey(bitcoin.TestNet) 288 | 289 | tx := wire.NewMsgTx(2) 290 | if err = addFakeInput(tx, sender); err != nil { 291 | t.Fatalf("Test %d failed to add input : %s", i+1, err) 292 | } 293 | if err = addFakeOutput(tx, receiver1); err != nil { 294 | t.Fatalf("Test %d failed to add output : %s", i+1, err) 295 | } 296 | if err = addFakeOutput(tx, receiver2); err != nil { 297 | t.Fatalf("Test %d failed to add output : %s", i+1, err) 298 | } 299 | 300 | err = message.AddEncryptedPayload(test.encryptedPayload, tx, 0, sender, 301 | []bitcoin.PublicKey{receiver1.PublicKey(), receiver2.PublicKey()}) 302 | if err != nil { 303 | t.Fatalf("Test %d add encrypted payload failed : %s", i+1, err) 304 | } 305 | 306 | var buf bytes.Buffer 307 | err = message.Serialize(&buf) 308 | if err != nil { 309 | t.Fatalf("Test %d failed serialize : %s", i, err) 310 | } 311 | 312 | reader := bytes.NewReader(buf.Bytes()) 313 | baseRead, err := Deserialize(reader) 314 | if err != nil { 315 | t.Fatalf("Test %d failed deserialize : %s", i, err) 316 | } 317 | read, ok := baseRead.(*v0.Message) 318 | if !ok { 319 | t.Fatalf("Test %d failed to convert read to v0 message", i+1) 320 | } 321 | 322 | if read.EncryptedPayloadCount() != 1 { 323 | t.Fatalf("Test %d wrong amount of encrypted payloads : %d", i, read.EncryptedPayloadCount()) 324 | } 325 | 326 | encryptedPayload := read.EncryptedPayload(0) 327 | encPayload, err := encryptedPayload.SenderDecrypt(tx, sender, receiver2.PublicKey()) 328 | if err != nil { 329 | t.Fatalf("Test %d failed decrypt : %s", i, err) 330 | } 331 | 332 | if !bytes.Equal(test.encryptedPayload, encPayload) { 333 | t.Fatalf("Test %d encrypted payload doesn't match :\nwant 0x%x\ngot 0x%x", i+1, 334 | test.encryptedPayload, encPayload) 335 | } 336 | } 337 | } 338 | 339 | func TestEncryptionProtobuf(t *testing.T) { 340 | mnIndex := &protobuf.MetaNet{ 341 | Index: 2, 342 | } 343 | mnParent := &protobuf.MetaNet{ 344 | Parent: []byte("01234567890123456789012345678901"), 345 | } 346 | encryptedPayload, err := proto.Marshal(mnIndex) 347 | if err != nil { 348 | t.Fatalf("Failed to serialize metanet index : %s", err) 349 | } 350 | payload, err := proto.Marshal(mnParent) 351 | if err != nil { 352 | t.Fatalf("Failed to serialize metanet parent : %s", err) 353 | } 354 | 355 | message := v0.NewMessage([]byte("test"), 0, payload) 356 | sender, err := bitcoin.GenerateKey(bitcoin.TestNet) 357 | receiver1, err := bitcoin.GenerateKey(bitcoin.TestNet) 358 | receiver2, err := bitcoin.GenerateKey(bitcoin.TestNet) 359 | 360 | tx := wire.NewMsgTx(2) 361 | if err = addFakeInput(tx, sender); err != nil { 362 | t.Fatalf("Test failed to add input : %s", err) 363 | } 364 | if err = addFakeOutput(tx, receiver1); err != nil { 365 | t.Fatalf("Test failed to add output : %s", err) 366 | } 367 | if err = addFakeOutput(tx, receiver2); err != nil { 368 | t.Fatalf("Test failed to add output : %s", err) 369 | } 370 | 371 | err = message.AddEncryptedPayload(encryptedPayload, tx, 0, sender, 372 | []bitcoin.PublicKey{receiver1.PublicKey(), receiver2.PublicKey()}) 373 | if err != nil { 374 | t.Fatalf("Test add encrypted payload failed : %s", err) 375 | } 376 | 377 | var buf bytes.Buffer 378 | err = message.Serialize(&buf) 379 | if err != nil { 380 | t.Fatalf("Test failed serialize : %s", err) 381 | } 382 | 383 | reader := bytes.NewReader(buf.Bytes()) 384 | baseRead, err := Deserialize(reader) 385 | if err != nil { 386 | t.Fatalf("Test failed deserialize : %s", err) 387 | } 388 | read, ok := baseRead.(*v0.Message) 389 | if !ok { 390 | t.Fatalf("Test failed to convert read to v0 message") 391 | } 392 | 393 | if read.EncryptedPayloadCount() != 1 { 394 | t.Fatalf("Test wrong amount of encrypted payloads : %d", read.EncryptedPayloadCount()) 395 | } 396 | 397 | readEncryptedPayload := read.EncryptedPayload(0) 398 | encPayload, err := readEncryptedPayload.SenderDecrypt(tx, sender, receiver2.PublicKey()) 399 | if err != nil { 400 | t.Fatalf("Test failed decrypt : %s", err) 401 | } 402 | 403 | if !bytes.Equal(encryptedPayload, encPayload) { 404 | t.Fatalf("Test encrypted payload doesn't match :\nwant 0x%x\ngot 0x%x", encryptedPayload, encPayload) 405 | } 406 | 407 | compositePayload := append(encPayload, read.Payload()...) 408 | 409 | var readMN protobuf.MetaNet 410 | if err = proto.Unmarshal(compositePayload, &readMN); err != nil { 411 | t.Fatalf("Test failed unmarshal protobuf : %s", err) 412 | } 413 | 414 | if readMN.GetIndex() != mnIndex.GetIndex() { 415 | t.Fatalf("Test failed MetaNet index mismatch : got %d want %d", readMN.GetIndex(), mnIndex.GetIndex()) 416 | } 417 | 418 | if !bytes.Equal(readMN.GetParent(), mnParent.GetParent()) { 419 | t.Fatalf("Test failed MetaNet index mismatch : got %x want %x", readMN.GetParent(), mnParent.GetParent()) 420 | } 421 | } 422 | 423 | func addFakeInput(tx *wire.MsgTx, key bitcoin.Key) error { 424 | var fakeScriptBuf bytes.Buffer 425 | err := bitcoin.WritePushDataScript(&fakeScriptBuf, key.PublicKey().Bytes()) 426 | if err != nil { 427 | return err 428 | } 429 | err = bitcoin.WritePushDataScript(&fakeScriptBuf, []byte("fake signature")) 430 | if err != nil { 431 | return err 432 | } 433 | tx.TxIn = append(tx.TxIn, &wire.TxIn{ 434 | UnlockingScript: fakeScriptBuf.Bytes(), 435 | Sequence: 0xffffffff, 436 | }) 437 | return nil 438 | } 439 | 440 | func addFakeOutput(tx *wire.MsgTx, key bitcoin.Key) error { 441 | address, err := bitcoin.NewRawAddressPKH(bitcoin.Hash160(key.PublicKey().Bytes())) 442 | if err != nil { 443 | return err 444 | } 445 | var fakeScriptBuf bytes.Buffer 446 | err = bitcoin.WritePushDataScript(&fakeScriptBuf, key.PublicKey().Bytes()) 447 | if err != nil { 448 | return err 449 | } 450 | err = bitcoin.WritePushDataScript(&fakeScriptBuf, []byte("fake signature")) 451 | if err != nil { 452 | return err 453 | } 454 | script, err := address.LockingScript() 455 | if err != nil { 456 | return err 457 | } 458 | tx.TxOut = append(tx.TxOut, &wire.TxOut{ 459 | LockingScript: script, 460 | Value: 100, 461 | }) 462 | return nil 463 | } 464 | -------------------------------------------------------------------------------- /pkg/golang/envelope/envelope_v1_test.go: -------------------------------------------------------------------------------- 1 | package envelope 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | 7 | "github.com/tokenized/envelope/pkg/golang/envelope/base" 8 | v1 "github.com/tokenized/envelope/pkg/golang/envelope/v1" 9 | ) 10 | 11 | var v1RetentionTests = []struct { 12 | protocolIDs base.ProtocolIDs 13 | payloads [][]byte 14 | }{ 15 | { 16 | protocolIDs: base.ProtocolIDs{base.ProtocolID("tokenized")}, 17 | payloads: [][]byte{[]byte("T1"), []byte("Test data 1")}, 18 | }, 19 | { 20 | protocolIDs: base.ProtocolIDs{base.ProtocolID("test")}, 21 | payloads: [][]byte{[]byte("5")}, 22 | }, 23 | { 24 | protocolIDs: base.ProtocolIDs{base.ProtocolID{0xbe, 0xef}}, 25 | payloads: nil, 26 | }, 27 | { 28 | protocolIDs: base.ProtocolIDs{base.ProtocolID{0xbe, 0xef}}, 29 | payloads: nil, 30 | }, 31 | } 32 | 33 | func TestRetentionV1(t *testing.T) { 34 | for i, test := range v1RetentionTests { 35 | message := v1.NewMessage(test.protocolIDs, test.payloads) 36 | 37 | var buf bytes.Buffer 38 | err := message.Serialize(&buf) 39 | if err != nil { 40 | t.Fatalf("Test %d Failed Serialize : %s", i, err) 41 | } 42 | 43 | reader := bytes.NewReader(buf.Bytes()) 44 | readBase, err := Deserialize(reader) 45 | if err != nil { 46 | t.Fatalf("Test %d Failed Deserialize : %s", i, err) 47 | } 48 | 49 | read, ok := readBase.(*v1.Message) 50 | if !ok { 51 | t.Fatalf("Wrong message type") 52 | } 53 | 54 | protocolIDs := read.PayloadProtocols() 55 | if len(protocolIDs) != len(test.protocolIDs) { 56 | t.Fatalf("Wrong protocol ID count : got %d, want %d", len(protocolIDs), 57 | len(test.protocolIDs)) 58 | } 59 | 60 | payloadCount := read.PayloadCount() 61 | if payloadCount != len(test.payloads) { 62 | t.Fatalf("Wrong payload count : got %d, want %d", payloadCount, len(test.payloads)) 63 | } 64 | 65 | for i, protocolID := range protocolIDs { 66 | if !bytes.Equal(protocolID, test.protocolIDs[i]) { 67 | t.Errorf("Wrong protocol ID %d : \ngot : %x\nwant : %x", i, protocolID, 68 | test.protocolIDs[i]) 69 | } 70 | 71 | t.Logf("Verified protocol ID %d : %x", i, protocolID) 72 | } 73 | 74 | for i := 0; i < payloadCount; i++ { 75 | payload := read.PayloadAt(i) 76 | if !bytes.Equal(payload, test.payloads[i]) { 77 | t.Errorf("Wrong payload %d : \ngot : %x\nwant : %x", i, payload, 78 | test.payloads[i]) 79 | } 80 | 81 | t.Logf("Verified payload %d : %x", i, payload) 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /pkg/golang/envelope/v0/decryption.go: -------------------------------------------------------------------------------- 1 | package v0 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | 7 | "github.com/tokenized/pkg/bitcoin" 8 | "github.com/tokenized/pkg/wire" 9 | 10 | "github.com/pkg/errors" 11 | ) 12 | 13 | var ( 14 | ErrDecryptInvalid = errors.New("Decrypt invalid") 15 | ) 16 | 17 | func (ep *EncryptedPayload) EncryptionType() uint32 { 18 | return ep.encryptionType 19 | } 20 | 21 | func (ep *EncryptedPayload) SenderPublicKey(tx *wire.MsgTx) (bitcoin.PublicKey, error) { 22 | if int(ep.sender) >= len(tx.TxIn) { 23 | return bitcoin.PublicKey{}, fmt.Errorf("Sender index out of range : %d/%d", ep.sender, 24 | len(tx.TxIn)) 25 | } 26 | 27 | spk, err := bitcoin.PublicKeyFromUnlockingScript(tx.TxIn[ep.sender].UnlockingScript) 28 | if err != nil { 29 | return bitcoin.PublicKey{}, err 30 | } 31 | 32 | return bitcoin.PublicKeyFromBytes(spk) 33 | } 34 | 35 | func (ep *EncryptedPayload) ReceiverAddresses(tx *wire.MsgTx) ([]bitcoin.RawAddress, error) { 36 | result := make([]bitcoin.RawAddress, 0, len(ep.receivers)) 37 | for _, receiver := range ep.receivers { 38 | if int(receiver.index) >= len(tx.TxOut) { 39 | return nil, fmt.Errorf("Receiver index out of range : %d/%d", receiver.index, 40 | len(tx.TxOut)) 41 | } 42 | 43 | ra, err := bitcoin.RawAddressFromLockingScript(tx.TxOut[receiver.index].LockingScript) 44 | if err != nil { 45 | continue 46 | } 47 | 48 | result = append(result, ra) 49 | } 50 | 51 | return result, nil 52 | } 53 | 54 | // IndirectDecrypt decrypts the payload using the specified secret. 55 | func (ep *EncryptedPayload) IndirectDecrypt(encryptionKey bitcoin.Hash32) ([]byte, error) { 56 | return bitcoin.Decrypt(ep.payload, encryptionKey.Bytes()) 57 | } 58 | 59 | // SenderDecrypt decrypts the payload using the sender's private key and a receiver's public key. 60 | func (ep *EncryptedPayload) SenderDecrypt(tx *wire.MsgTx, senderKey bitcoin.Key, 61 | receiverPubKey bitcoin.PublicKey) ([]byte, error) { 62 | payload, _, err := ep.SenderDecryptKey(tx, senderKey, receiverPubKey) 63 | return payload, err 64 | } 65 | 66 | // SenderDecryptKey decrypts the payload using the sender's private key and a receiver's public key. 67 | func (ep *EncryptedPayload) SenderDecryptKey(tx *wire.MsgTx, senderKey bitcoin.Key, 68 | receiverPubKey bitcoin.PublicKey) ([]byte, bitcoin.Hash32, error) { 69 | 70 | if ep.encryptionType != 0 { 71 | return nil, bitcoin.Hash32{}, errors.Wrap(ErrDecryptInvalid, "Indirect") 72 | } 73 | 74 | // Find sender 75 | if ep.sender >= uint32(len(tx.TxIn)) { 76 | return nil, bitcoin.Hash32{}, errors.New("Sender index out of range") 77 | } 78 | 79 | senderPubKeyData, err := bitcoin.PublicKeyFromUnlockingScript(tx.TxIn[ep.sender].UnlockingScript) 80 | if err != nil { 81 | return nil, bitcoin.Hash32{}, err 82 | } 83 | 84 | senderPubKey, err := bitcoin.PublicKeyFromBytes(senderPubKeyData) 85 | if err != nil { 86 | return nil, bitcoin.Hash32{}, err 87 | } 88 | 89 | if !bytes.Equal(senderPubKey.Bytes(), senderKey.PublicKey().Bytes()) { 90 | return nil, bitcoin.Hash32{}, errors.New("Wrong sender key") 91 | } 92 | 93 | if len(ep.receivers) == 0 { 94 | key, _ := bitcoin.NewHash32(bitcoin.Sha256(senderKey.Number())) 95 | payload, err := bitcoin.Decrypt(ep.payload, key.Bytes()) 96 | return payload, *key, err 97 | } 98 | 99 | if receiverPubKey.IsEmpty() { 100 | return nil, bitcoin.Hash32{}, errors.New("Receiver public key required") 101 | } 102 | 103 | // Find receiver 104 | pkh, _ := bitcoin.NewHash20(bitcoin.Hash160(receiverPubKey.Bytes())) 105 | for _, receiver := range ep.receivers { 106 | if receiver.index >= uint32(len(tx.TxOut)) { 107 | continue 108 | } 109 | 110 | rawAddress, err := bitcoin.RawAddressFromLockingScript(tx.TxOut[receiver.index].LockingScript) 111 | if err != nil { 112 | continue 113 | } 114 | 115 | hash, err := rawAddress.GetPublicKeyHash() 116 | matches := err == nil && hash.Equal(pkh) 117 | 118 | if !matches { 119 | key, err := rawAddress.GetPublicKey() 120 | matches = err == nil && key.Equal(receiverPubKey) 121 | } 122 | 123 | if !matches { 124 | continue 125 | } 126 | 127 | if len(receiver.encryptedKey) == 0 { 128 | if len(ep.receivers) != 1 { 129 | // For more than one receiver, an encrypted key must be provided. 130 | return nil, bitcoin.Hash32{}, errors.New("Missing encryption key for receiver") 131 | } 132 | 133 | // Use DH secret 134 | secret, err := bitcoin.ECDHSecret(senderKey, receiverPubKey) 135 | if err != nil { 136 | return nil, bitcoin.Hash32{}, err 137 | } 138 | encryptionKey, _ := bitcoin.NewHash32(bitcoin.Sha256(secret)) 139 | 140 | payload, err := bitcoin.Decrypt(ep.payload, encryptionKey.Bytes()) 141 | return payload, *encryptionKey, err 142 | } else { 143 | // Decrypt key using DH key 144 | secret, err := bitcoin.ECDHSecret(senderKey, receiverPubKey) 145 | if err != nil { 146 | return nil, bitcoin.Hash32{}, err 147 | } 148 | dhKey := bitcoin.Sha256(secret) 149 | 150 | encryptionKey, err := bitcoin.Decrypt(receiver.encryptedKey, dhKey) 151 | if err != nil { 152 | return nil, bitcoin.Hash32{}, err 153 | } 154 | 155 | key, _ := bitcoin.NewHash32(encryptionKey) 156 | 157 | payload, err := bitcoin.Decrypt(ep.payload, encryptionKey) 158 | return payload, *key, err 159 | } 160 | } 161 | 162 | return nil, bitcoin.Hash32{}, errors.New("Matching receiver not found") 163 | } 164 | 165 | // ReceiverDecrypt decrypts the payload using the receiver's private key. 166 | func (ep *EncryptedPayload) ReceiverDecrypt(tx *wire.MsgTx, receiverKey bitcoin.Key) ([]byte, error) { 167 | result, _, err := ep.ReceiverDecryptKey(tx, receiverKey) 168 | return result, err 169 | } 170 | 171 | // ReceiverDecryptKey decrypts the payload using the receiver's private key and returns the 172 | // encryption key. 173 | func (ep *EncryptedPayload) ReceiverDecryptKey(tx *wire.MsgTx, receiverKey bitcoin.Key) ([]byte, bitcoin.Hash32, error) { 174 | 175 | if ep.encryptionType != 0 { 176 | return nil, bitcoin.Hash32{}, errors.Wrap(ErrDecryptInvalid, "Indirect") 177 | } 178 | 179 | if len(ep.receivers) == 0 { 180 | return nil, bitcoin.Hash32{}, errors.New("No receivers") 181 | } 182 | 183 | // Find sender 184 | if ep.sender >= uint32(len(tx.TxIn)) { 185 | return nil, bitcoin.Hash32{}, errors.New("Sender index out of range") 186 | } 187 | 188 | senderPubKeyData, err := bitcoin.PublicKeyFromUnlockingScript(tx.TxIn[ep.sender].UnlockingScript) 189 | if err != nil { 190 | return nil, bitcoin.Hash32{}, err 191 | } 192 | 193 | senderPubKey, err := bitcoin.PublicKeyFromBytes(senderPubKeyData) 194 | if err != nil { 195 | return nil, bitcoin.Hash32{}, err 196 | } 197 | 198 | // Find receiver 199 | pk := receiverKey.PublicKey() 200 | pkh, _ := bitcoin.NewHash20(bitcoin.Hash160(pk.Bytes())) 201 | for _, receiver := range ep.receivers { 202 | if receiver.index >= uint32(len(tx.TxOut)) { 203 | continue 204 | } 205 | 206 | rawAddress, err := bitcoin.RawAddressFromLockingScript(tx.TxOut[receiver.index].LockingScript) 207 | if err != nil { 208 | continue 209 | } 210 | 211 | hash, err := rawAddress.GetPublicKeyHash() 212 | matches := err == nil && hash.Equal(pkh) 213 | 214 | if !matches { 215 | key, err := rawAddress.GetPublicKey() 216 | matches = err == nil && key.Equal(pk) 217 | } 218 | 219 | if !matches { 220 | continue 221 | } 222 | 223 | if len(receiver.encryptedKey) == 0 { 224 | if len(ep.receivers) != 1 { 225 | // For more than one receiver, an encrypted key must be provided. 226 | return nil, bitcoin.Hash32{}, errors.New("Missing encryption key for receiver") 227 | } 228 | 229 | // Use DH secret 230 | secret, err := bitcoin.ECDHSecret(receiverKey, senderPubKey) 231 | if err != nil { 232 | return nil, bitcoin.Hash32{}, err 233 | } 234 | encryptionKey, _ := bitcoin.NewHash32(bitcoin.Sha256(secret)) 235 | 236 | result, err := bitcoin.Decrypt(ep.payload, encryptionKey.Bytes()) 237 | return result, *encryptionKey, err 238 | } else { 239 | // Decrypt key using DH key 240 | secret, err := bitcoin.ECDHSecret(receiverKey, senderPubKey) 241 | if err != nil { 242 | return nil, bitcoin.Hash32{}, err 243 | } 244 | dhKey := bitcoin.Sha256(secret) 245 | 246 | encryptionKey, err := bitcoin.Decrypt(receiver.encryptedKey, dhKey) 247 | if err != nil { 248 | return nil, bitcoin.Hash32{}, err 249 | } 250 | 251 | key, err := bitcoin.NewHash32(encryptionKey) 252 | if err != nil { 253 | return nil, bitcoin.Hash32{}, err 254 | } 255 | 256 | result, err := bitcoin.Decrypt(ep.payload, encryptionKey) 257 | return result, *key, err 258 | } 259 | } 260 | 261 | return nil, bitcoin.Hash32{}, errors.New("Matching receiver not found") 262 | } 263 | -------------------------------------------------------------------------------- /pkg/golang/envelope/v0/encryption.go: -------------------------------------------------------------------------------- 1 | package v0 2 | 3 | import ( 4 | "crypto/rand" 5 | "errors" 6 | 7 | "github.com/tokenized/pkg/bitcoin" 8 | "github.com/tokenized/pkg/wire" 9 | ) 10 | 11 | // NewEncryptedPayload creates an encrypted payload. The encryption information is contained in the 12 | // tx. A private key of the sender or one of the receivers is necessary to decrypt. 13 | // If there are more than one receivers. A random encryption secret is generated and encrypted to 14 | // each receiver. 15 | func NewEncryptedPayload(payload []byte, tx *wire.MsgTx, senderIndex uint32, sender bitcoin.Key, 16 | receivers []bitcoin.PublicKey) (*EncryptedPayload, error) { 17 | result, _, err := NewEncryptedPayloadDirect(payload, tx, senderIndex, sender, receivers) 18 | return result, err 19 | } 20 | 21 | // NewEncryptedPayloadDirect creates an encrypted payload. 22 | // Returns: 23 | // encrypted payload 24 | // encryption key 25 | // error, if there is one 26 | func NewEncryptedPayloadDirect(payload []byte, tx *wire.MsgTx, senderIndex uint32, sender bitcoin.Key, 27 | receivers []bitcoin.PublicKey) (*EncryptedPayload, bitcoin.Hash32, error) { 28 | 29 | result := &EncryptedPayload{sender: senderIndex} 30 | var encryptionKey *bitcoin.Hash32 31 | 32 | if len(receivers) == 0 { // Private to sender 33 | encryptionKey, _ = bitcoin.NewHash32(bitcoin.Sha256(sender.Number())) 34 | } else if len(receivers) == 1 { // One receiver 35 | // Find receiver's output 36 | pkh, _ := bitcoin.NewHash20(bitcoin.Hash160(receivers[0].Bytes())) 37 | receiverIndex := uint32(0) 38 | found := false 39 | for index, output := range tx.TxOut { 40 | rawAddress, err := bitcoin.RawAddressFromLockingScript(output.LockingScript) 41 | if err != nil { 42 | continue 43 | } 44 | 45 | hash, err := rawAddress.GetPublicKeyHash() 46 | if err == nil && hash.Equal(pkh) { 47 | found = true 48 | receiverIndex = uint32(index) 49 | break 50 | } 51 | 52 | key, err := rawAddress.GetPublicKey() 53 | if err == nil && key.Equal(receivers[0]) { 54 | found = true 55 | receiverIndex = uint32(index) 56 | break 57 | } 58 | } 59 | if !found { 60 | return nil, bitcoin.Hash32{}, errors.New("Receiver output not found") 61 | } 62 | result.receivers = []*Receiver{ 63 | &Receiver{index: receiverIndex}, // No encrypted key required since it is derivable. 64 | } 65 | 66 | // Encryption key is derived using ECDH with sender's private key and receiver's public key. 67 | secret, err := bitcoin.ECDHSecret(sender, receivers[0]) 68 | if err != nil { 69 | return nil, bitcoin.Hash32{}, err 70 | } 71 | encryptionKey, _ = bitcoin.NewHash32(bitcoin.Sha256(secret)) 72 | 73 | } else { // Multiple receivers 74 | // Encryption key is random and encrypted to each receiver. 75 | encryptionKey = &bitcoin.Hash32{} 76 | _, err := rand.Read(encryptionKey[:]) 77 | if err != nil { 78 | return nil, bitcoin.Hash32{}, err 79 | } 80 | 81 | // Find each receiver's output and encrypt key using their DH secret. 82 | for _, receiver := range receivers { 83 | pkh, _ := bitcoin.NewHash20(bitcoin.Hash160(receiver.Bytes())) 84 | receiverIndex := uint32(0) 85 | found := false 86 | for index, output := range tx.TxOut { 87 | rawAddress, err := bitcoin.RawAddressFromLockingScript(output.LockingScript) 88 | if err != nil { 89 | continue 90 | } 91 | 92 | hash, err := rawAddress.GetPublicKeyHash() 93 | if err == nil && hash.Equal(pkh) { 94 | found = true 95 | receiverIndex = uint32(index) 96 | break 97 | } 98 | 99 | key, err := rawAddress.GetPublicKey() 100 | if err == nil && key.Equal(receiver) { 101 | found = true 102 | receiverIndex = uint32(index) 103 | break 104 | } 105 | } 106 | if !found { 107 | return nil, bitcoin.Hash32{}, errors.New("Receiver output not found") 108 | } 109 | 110 | receiverSecret, err := bitcoin.ECDHSecret(sender, receiver) 111 | if err != nil { 112 | return nil, bitcoin.Hash32{}, err 113 | } 114 | receiverKey := bitcoin.Sha256(receiverSecret) 115 | 116 | encryptedKey, err := bitcoin.Encrypt(encryptionKey.Bytes(), receiverKey) 117 | if err != nil { 118 | return nil, bitcoin.Hash32{}, err 119 | } 120 | 121 | result.receivers = append(result.receivers, &Receiver{ 122 | index: receiverIndex, 123 | encryptedKey: encryptedKey, 124 | }) 125 | } 126 | } 127 | 128 | var err error 129 | result.payload, err = bitcoin.Encrypt(payload, encryptionKey.Bytes()) 130 | if err != nil { 131 | return nil, bitcoin.Hash32{}, err 132 | } 133 | 134 | return result, *encryptionKey, nil 135 | } 136 | 137 | // NewEncryptedPayloadIndirect creates an encryped payload that is encrypted with the specified 138 | // key instead of with keys in the message. 139 | func NewEncryptedPayloadIndirect(payload []byte, tx *wire.MsgTx, key bitcoin.Hash32) (*EncryptedPayload, error) { 140 | 141 | result := &EncryptedPayload{encryptionType: 1} 142 | 143 | var err error 144 | result.payload, err = bitcoin.Encrypt(payload, key.Bytes()) 145 | if err != nil { 146 | return nil, err 147 | } 148 | 149 | return result, nil 150 | } 151 | -------------------------------------------------------------------------------- /pkg/golang/envelope/v0/metanet.go: -------------------------------------------------------------------------------- 1 | package v0 2 | 3 | import ( 4 | "github.com/tokenized/pkg/bitcoin" 5 | "github.com/tokenized/pkg/wire" 6 | 7 | "github.com/pkg/errors" 8 | ) 9 | 10 | type MetaNet struct { 11 | index uint32 12 | publicKey bitcoin.PublicKey 13 | parent []byte 14 | } 15 | 16 | func NewMetaNet(index uint32, publicKey bitcoin.PublicKey, parent []byte) *MetaNet { 17 | return &MetaNet{ 18 | index: index, 19 | publicKey: publicKey, 20 | parent: parent, 21 | } 22 | } 23 | 24 | func (mn *MetaNet) Index() uint32 { 25 | return mn.index 26 | } 27 | 28 | func (mn *MetaNet) PublicKey(tx *wire.MsgTx) (bitcoin.PublicKey, error) { 29 | if mn.publicKey.IsEmpty() { 30 | return mn.publicKey, nil 31 | } 32 | 33 | if int(mn.index) >= len(tx.TxIn) { 34 | return bitcoin.PublicKey{}, errors.New("Index out of range") 35 | } 36 | 37 | pubKey, err := bitcoin.PublicKeyFromUnlockingScript(tx.TxIn[mn.index].UnlockingScript) 38 | if err != nil { 39 | return bitcoin.PublicKey{}, err 40 | } 41 | 42 | mn.publicKey, err = bitcoin.PublicKeyFromBytes(pubKey) 43 | if err != nil { 44 | return bitcoin.PublicKey{}, err 45 | } 46 | 47 | return mn.publicKey, nil 48 | } 49 | 50 | func (mn *MetaNet) Parent() []byte { 51 | return mn.parent 52 | } 53 | -------------------------------------------------------------------------------- /pkg/golang/envelope/v0/models.go: -------------------------------------------------------------------------------- 1 | package v0 2 | 3 | import ( 4 | "github.com/tokenized/envelope/pkg/golang/envelope/base" 5 | "github.com/tokenized/pkg/bitcoin" 6 | "github.com/tokenized/pkg/wire" 7 | ) 8 | 9 | type Message struct { 10 | payloadProtocol base.ProtocolID // Protocol ID of payload. (recommended to be ascii text) 11 | payloadVersion uint64 // Protocol specific version for the payload. 12 | payloadType []byte // Data type of payload. 13 | payloadIdentifier []byte // Protocol specific identifier for the payload. (i.e. message type, data name) 14 | metaNet *MetaNet 15 | encryptedPayloads []*EncryptedPayload 16 | payload []byte 17 | } 18 | 19 | // EncryptedPayload holds encrypted data. 20 | // The data will be encrypted in different ways depending on the number of receivers. 21 | // 22 | // Sender: 23 | // Sender's input must be a P2PKH or a P2RPH unlocking script so that it contains the public key. 24 | // 25 | // Receivers: 26 | // Receiver's outputs must be P2PKH locking scripts so that it contains the hash of the public 27 | // key. 28 | // 0 receivers - data is encrypted with sender's private key. 29 | // 1 receiver - data is encrypted with a derived shared secret. 30 | // 2 receivers - data is encrypted with a random private key and the private key is encrypted 31 | // with the derived shared secret of each receiver and included in the message. 32 | // 33 | // EncryptionType: 34 | // 0 Direct - encryption secret based on public keys in transaction pointed to by sender and 35 | // receivers. 36 | // 1 Indirect - encryption secret is from previous context. 37 | type EncryptedPayload struct { 38 | sender uint32 39 | receivers []*Receiver 40 | payload []byte // Data that is to be or was encrypted 41 | encryptionType uint32 42 | } 43 | 44 | // Index to receiver and if more than one, encrypted keys 45 | type Receiver struct { 46 | index uint32 47 | encryptedKey []byte 48 | } 49 | 50 | // NewMessage creates a message. 51 | func NewMessage(protocol base.ProtocolID, version uint64, payload []byte) *Message { 52 | return &Message{payloadProtocol: protocol, payloadVersion: version, payload: payload} 53 | } 54 | 55 | func (m *Message) EnvelopeVersion() uint8 { 56 | return 0 57 | } 58 | 59 | func (m *Message) PayloadProtocols() base.ProtocolIDs { 60 | return base.ProtocolIDs{m.payloadProtocol} 61 | } 62 | 63 | func (m *Message) PayloadCount() int { 64 | return 1 65 | } 66 | 67 | func (m *Message) PayloadAt(offset int) []byte { 68 | if offset != 0 { 69 | return nil 70 | } 71 | 72 | return m.payload 73 | } 74 | 75 | func (m *Message) PayloadProtocol() base.ProtocolID { 76 | return m.payloadProtocol 77 | } 78 | 79 | func (m *Message) PayloadVersion() uint64 { 80 | return m.payloadVersion 81 | } 82 | 83 | func (m *Message) PayloadType() []byte { 84 | return m.payloadType 85 | } 86 | 87 | func (m *Message) PayloadIdentifier() []byte { 88 | return m.payloadIdentifier 89 | } 90 | 91 | func (m *Message) MetaNet() *MetaNet { 92 | return m.metaNet 93 | } 94 | 95 | func (m *Message) EncryptedPayloadCount() int { 96 | return len(m.encryptedPayloads) 97 | } 98 | 99 | func (m *Message) EncryptedPayload(i int) *EncryptedPayload { 100 | return m.encryptedPayloads[i] 101 | } 102 | 103 | func (m *Message) Payload() []byte { 104 | return m.payload 105 | } 106 | 107 | func (m *Message) SetPayload(b []byte) { 108 | m.payload = b 109 | } 110 | 111 | func (m *Message) SetPayloadType(t []byte) { 112 | m.payloadType = t 113 | } 114 | 115 | func (m *Message) SetPayloadIdentifier(i []byte) { 116 | m.payloadIdentifier = i 117 | } 118 | 119 | // AddMetaNet adds MetaNet data to the message. 120 | // index is the input index that will contain the public key. Note, it will not contain the public 121 | // key when this function is called because it has not yet been signed. The public key will be in 122 | // the signature script after the input has been signed. The input must be P2PKH or P2RPH. 123 | // If there is not parent then just use nil for parent. 124 | func (m *Message) SetMetaNet(index uint32, publicKey bitcoin.PublicKey, parent []byte) { 125 | m.metaNet = NewMetaNet(index, publicKey, parent) 126 | } 127 | 128 | // AddEncryptedPayload creates an encrypted payload object and adds it to the message. 129 | // senderIndex is the input index containing the public key of the creator of the encrypted payload. 130 | // sender is the key used to create the encrypted payload. 131 | // receivers are the public keys of those receiving the encrypted payload. 132 | // The data will be encrypted in different ways depending on the number of receivers. 133 | // 134 | // Sender: 135 | // Sender's input must be a P2PKH or a P2RPH unlocking script so that it contains the public key. 136 | // 137 | // Receivers: 138 | // Receiver's outputs must be P2PKH locking scripts so that it contains the hash of the public 139 | // key. 140 | // 0 receivers - data is encrypted with sender's private key. 141 | // 1 receiver - data is encrypted with a derived shared secret. 142 | // 2 receivers - data is encrypted with a random private key and the private key is encrypted 143 | // with the derived shared secret of each receiver and included in the message. 144 | func (m *Message) AddEncryptedPayload(payload []byte, tx *wire.MsgTx, senderIndex uint32, 145 | sender bitcoin.Key, receivers []bitcoin.PublicKey) error { 146 | encryptedPayload, err := NewEncryptedPayload(payload, tx, senderIndex, sender, 147 | receivers) 148 | if err != nil { 149 | return err 150 | } 151 | m.encryptedPayloads = append(m.encryptedPayloads, encryptedPayload) 152 | return nil 153 | } 154 | 155 | // AddEncryptedPayloadDirect creates an encrypted payload with all information necessary to decrypt, 156 | // except the private key, included in the message. 157 | func (m *Message) AddEncryptedPayloadDirect(payload []byte, tx *wire.MsgTx, senderIndex uint32, 158 | sender bitcoin.Key, receivers []bitcoin.PublicKey) (bitcoin.Hash32, error) { 159 | encryptedPayload, key, err := NewEncryptedPayloadDirect(payload, tx, senderIndex, sender, 160 | receivers) 161 | if err != nil { 162 | return key, err 163 | } 164 | m.encryptedPayloads = append(m.encryptedPayloads, encryptedPayload) 165 | return key, nil 166 | } 167 | 168 | // AddEncryptedPayloadIndirect creates an encryped payload and adds it to the message. The message 169 | // is encrypted with the specified key instead of with keys in the message. 170 | func (m *Message) AddEncryptedPayloadIndirect(payload []byte, tx *wire.MsgTx, key bitcoin.Hash32) error { 171 | encryptedPayload, err := NewEncryptedPayloadIndirect(payload, tx, key) 172 | if err != nil { 173 | return err 174 | } 175 | m.encryptedPayloads = append(m.encryptedPayloads, encryptedPayload) 176 | return nil 177 | } 178 | -------------------------------------------------------------------------------- /pkg/golang/envelope/v0/protobuf/envelope.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: envelope.proto 3 | 4 | package protobuf 5 | 6 | import ( 7 | fmt "fmt" 8 | math "math" 9 | 10 | proto "github.com/golang/protobuf/proto" 11 | ) 12 | 13 | // Reference imports to suppress errors if they are not otherwise used. 14 | var _ = proto.Marshal 15 | var _ = fmt.Errorf 16 | var _ = math.Inf 17 | 18 | // This is a compile-time assertion to ensure that this generated file 19 | // is compatible with the proto package it is being compiled against. 20 | // A compilation error at this line likely means your copy of the 21 | // proto package needs to be updated. 22 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 23 | 24 | type Envelope struct { 25 | Version uint64 `protobuf:"varint,1,opt,name=Version,proto3" json:"Version,omitempty"` 26 | Type []byte `protobuf:"bytes,2,opt,name=Type,proto3" json:"Type,omitempty"` 27 | Identifier []byte `protobuf:"bytes,3,opt,name=Identifier,proto3" json:"Identifier,omitempty"` 28 | MetaNet *MetaNet `protobuf:"bytes,4,opt,name=MetaNet,proto3" json:"MetaNet,omitempty"` 29 | EncryptedPayloads []*EncryptedPayload `protobuf:"bytes,5,rep,name=EncryptedPayloads,proto3" json:"EncryptedPayloads,omitempty"` 30 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 31 | XXX_unrecognized []byte `json:"-"` 32 | XXX_sizecache int32 `json:"-"` 33 | } 34 | 35 | func (m *Envelope) Reset() { *m = Envelope{} } 36 | func (m *Envelope) String() string { return proto.CompactTextString(m) } 37 | func (*Envelope) ProtoMessage() {} 38 | func (*Envelope) Descriptor() ([]byte, []int) { 39 | return fileDescriptor_ee266e8c558e9dc5, []int{0} 40 | } 41 | 42 | func (m *Envelope) XXX_Unmarshal(b []byte) error { 43 | return xxx_messageInfo_Envelope.Unmarshal(m, b) 44 | } 45 | func (m *Envelope) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 46 | return xxx_messageInfo_Envelope.Marshal(b, m, deterministic) 47 | } 48 | func (m *Envelope) XXX_Merge(src proto.Message) { 49 | xxx_messageInfo_Envelope.Merge(m, src) 50 | } 51 | func (m *Envelope) XXX_Size() int { 52 | return xxx_messageInfo_Envelope.Size(m) 53 | } 54 | func (m *Envelope) XXX_DiscardUnknown() { 55 | xxx_messageInfo_Envelope.DiscardUnknown(m) 56 | } 57 | 58 | var xxx_messageInfo_Envelope proto.InternalMessageInfo 59 | 60 | func (m *Envelope) GetVersion() uint64 { 61 | if m != nil { 62 | return m.Version 63 | } 64 | return 0 65 | } 66 | 67 | func (m *Envelope) GetType() []byte { 68 | if m != nil { 69 | return m.Type 70 | } 71 | return nil 72 | } 73 | 74 | func (m *Envelope) GetIdentifier() []byte { 75 | if m != nil { 76 | return m.Identifier 77 | } 78 | return nil 79 | } 80 | 81 | func (m *Envelope) GetMetaNet() *MetaNet { 82 | if m != nil { 83 | return m.MetaNet 84 | } 85 | return nil 86 | } 87 | 88 | func (m *Envelope) GetEncryptedPayloads() []*EncryptedPayload { 89 | if m != nil { 90 | return m.EncryptedPayloads 91 | } 92 | return nil 93 | } 94 | 95 | type MetaNet struct { 96 | Index uint32 `protobuf:"varint,1,opt,name=Index,proto3" json:"Index,omitempty"` 97 | Parent []byte `protobuf:"bytes,2,opt,name=Parent,proto3" json:"Parent,omitempty"` 98 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 99 | XXX_unrecognized []byte `json:"-"` 100 | XXX_sizecache int32 `json:"-"` 101 | } 102 | 103 | func (m *MetaNet) Reset() { *m = MetaNet{} } 104 | func (m *MetaNet) String() string { return proto.CompactTextString(m) } 105 | func (*MetaNet) ProtoMessage() {} 106 | func (*MetaNet) Descriptor() ([]byte, []int) { 107 | return fileDescriptor_ee266e8c558e9dc5, []int{1} 108 | } 109 | 110 | func (m *MetaNet) XXX_Unmarshal(b []byte) error { 111 | return xxx_messageInfo_MetaNet.Unmarshal(m, b) 112 | } 113 | func (m *MetaNet) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 114 | return xxx_messageInfo_MetaNet.Marshal(b, m, deterministic) 115 | } 116 | func (m *MetaNet) XXX_Merge(src proto.Message) { 117 | xxx_messageInfo_MetaNet.Merge(m, src) 118 | } 119 | func (m *MetaNet) XXX_Size() int { 120 | return xxx_messageInfo_MetaNet.Size(m) 121 | } 122 | func (m *MetaNet) XXX_DiscardUnknown() { 123 | xxx_messageInfo_MetaNet.DiscardUnknown(m) 124 | } 125 | 126 | var xxx_messageInfo_MetaNet proto.InternalMessageInfo 127 | 128 | func (m *MetaNet) GetIndex() uint32 { 129 | if m != nil { 130 | return m.Index 131 | } 132 | return 0 133 | } 134 | 135 | func (m *MetaNet) GetParent() []byte { 136 | if m != nil { 137 | return m.Parent 138 | } 139 | return nil 140 | } 141 | 142 | type EncryptedPayload struct { 143 | Sender uint32 `protobuf:"varint,1,opt,name=Sender,proto3" json:"Sender,omitempty"` 144 | Receivers []*Receiver `protobuf:"bytes,2,rep,name=Receivers,proto3" json:"Receivers,omitempty"` 145 | Payload []byte `protobuf:"bytes,3,opt,name=Payload,proto3" json:"Payload,omitempty"` 146 | EncryptionType uint32 `protobuf:"varint,4,opt,name=EncryptionType,proto3" json:"EncryptionType,omitempty"` 147 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 148 | XXX_unrecognized []byte `json:"-"` 149 | XXX_sizecache int32 `json:"-"` 150 | } 151 | 152 | func (m *EncryptedPayload) Reset() { *m = EncryptedPayload{} } 153 | func (m *EncryptedPayload) String() string { return proto.CompactTextString(m) } 154 | func (*EncryptedPayload) ProtoMessage() {} 155 | func (*EncryptedPayload) Descriptor() ([]byte, []int) { 156 | return fileDescriptor_ee266e8c558e9dc5, []int{2} 157 | } 158 | 159 | func (m *EncryptedPayload) XXX_Unmarshal(b []byte) error { 160 | return xxx_messageInfo_EncryptedPayload.Unmarshal(m, b) 161 | } 162 | func (m *EncryptedPayload) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 163 | return xxx_messageInfo_EncryptedPayload.Marshal(b, m, deterministic) 164 | } 165 | func (m *EncryptedPayload) XXX_Merge(src proto.Message) { 166 | xxx_messageInfo_EncryptedPayload.Merge(m, src) 167 | } 168 | func (m *EncryptedPayload) XXX_Size() int { 169 | return xxx_messageInfo_EncryptedPayload.Size(m) 170 | } 171 | func (m *EncryptedPayload) XXX_DiscardUnknown() { 172 | xxx_messageInfo_EncryptedPayload.DiscardUnknown(m) 173 | } 174 | 175 | var xxx_messageInfo_EncryptedPayload proto.InternalMessageInfo 176 | 177 | func (m *EncryptedPayload) GetSender() uint32 { 178 | if m != nil { 179 | return m.Sender 180 | } 181 | return 0 182 | } 183 | 184 | func (m *EncryptedPayload) GetReceivers() []*Receiver { 185 | if m != nil { 186 | return m.Receivers 187 | } 188 | return nil 189 | } 190 | 191 | func (m *EncryptedPayload) GetPayload() []byte { 192 | if m != nil { 193 | return m.Payload 194 | } 195 | return nil 196 | } 197 | 198 | func (m *EncryptedPayload) GetEncryptionType() uint32 { 199 | if m != nil { 200 | return m.EncryptionType 201 | } 202 | return 0 203 | } 204 | 205 | type Receiver struct { 206 | Index uint32 `protobuf:"varint,1,opt,name=Index,proto3" json:"Index,omitempty"` 207 | EncryptedKey []byte `protobuf:"bytes,2,opt,name=EncryptedKey,proto3" json:"EncryptedKey,omitempty"` 208 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 209 | XXX_unrecognized []byte `json:"-"` 210 | XXX_sizecache int32 `json:"-"` 211 | } 212 | 213 | func (m *Receiver) Reset() { *m = Receiver{} } 214 | func (m *Receiver) String() string { return proto.CompactTextString(m) } 215 | func (*Receiver) ProtoMessage() {} 216 | func (*Receiver) Descriptor() ([]byte, []int) { 217 | return fileDescriptor_ee266e8c558e9dc5, []int{3} 218 | } 219 | 220 | func (m *Receiver) XXX_Unmarshal(b []byte) error { 221 | return xxx_messageInfo_Receiver.Unmarshal(m, b) 222 | } 223 | func (m *Receiver) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 224 | return xxx_messageInfo_Receiver.Marshal(b, m, deterministic) 225 | } 226 | func (m *Receiver) XXX_Merge(src proto.Message) { 227 | xxx_messageInfo_Receiver.Merge(m, src) 228 | } 229 | func (m *Receiver) XXX_Size() int { 230 | return xxx_messageInfo_Receiver.Size(m) 231 | } 232 | func (m *Receiver) XXX_DiscardUnknown() { 233 | xxx_messageInfo_Receiver.DiscardUnknown(m) 234 | } 235 | 236 | var xxx_messageInfo_Receiver proto.InternalMessageInfo 237 | 238 | func (m *Receiver) GetIndex() uint32 { 239 | if m != nil { 240 | return m.Index 241 | } 242 | return 0 243 | } 244 | 245 | func (m *Receiver) GetEncryptedKey() []byte { 246 | if m != nil { 247 | return m.EncryptedKey 248 | } 249 | return nil 250 | } 251 | 252 | func init() { 253 | proto.RegisterType((*Envelope)(nil), "protobuf.Envelope") 254 | proto.RegisterType((*MetaNet)(nil), "protobuf.MetaNet") 255 | proto.RegisterType((*EncryptedPayload)(nil), "protobuf.EncryptedPayload") 256 | proto.RegisterType((*Receiver)(nil), "protobuf.Receiver") 257 | } 258 | 259 | func init() { proto.RegisterFile("envelope.proto", fileDescriptor_ee266e8c558e9dc5) } 260 | 261 | var fileDescriptor_ee266e8c558e9dc5 = []byte{ 262 | // 339 bytes of a gzipped FileDescriptorProto 263 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x52, 0x4d, 0x4b, 0xeb, 0x40, 264 | 0x14, 0x25, 0x6d, 0xfa, 0xf1, 0x6e, 0xfb, 0xca, 0xeb, 0xf0, 0x78, 0x0c, 0x6f, 0x21, 0x21, 0x0b, 265 | 0x09, 0x08, 0x49, 0xa9, 0x0b, 0x57, 0x22, 0x88, 0x05, 0x8b, 0x28, 0x65, 0x14, 0x17, 0xee, 0xd2, 266 | 0xe6, 0x36, 0x0e, 0xad, 0x33, 0x61, 0x3a, 0x2d, 0xc6, 0x1f, 0xe3, 0x5f, 0xf2, 0x2f, 0x49, 0xc7, 267 | 0x99, 0x46, 0x2b, 0xae, 0x32, 0xe7, 0x9e, 0x33, 0xe7, 0xcc, 0xb9, 0x04, 0x7a, 0x28, 0x36, 0xb8, 268 | 0x94, 0x05, 0xc6, 0x85, 0x92, 0x5a, 0x92, 0xb6, 0xf9, 0x4c, 0xd7, 0xf3, 0xf0, 0xcd, 0x83, 0xf6, 269 | 0xc8, 0x92, 0x84, 0x42, 0xeb, 0x1e, 0xd5, 0x8a, 0x4b, 0x41, 0xbd, 0xc0, 0x8b, 0x7c, 0xe6, 0x20, 270 | 0x21, 0xe0, 0xdf, 0x95, 0x05, 0xd2, 0x5a, 0xe0, 0x45, 0x5d, 0x66, 0xce, 0xe4, 0x00, 0x60, 0x9c, 271 | 0xa1, 0xd0, 0x7c, 0xce, 0x51, 0xd1, 0xba, 0x61, 0x3e, 0x4d, 0xc8, 0x11, 0xb4, 0xae, 0x51, 0xa7, 272 | 0x37, 0xa8, 0xa9, 0x1f, 0x78, 0x51, 0x67, 0xd8, 0x8f, 0x5d, 0x6c, 0x6c, 0x09, 0xe6, 0x14, 0xe4, 273 | 0x12, 0xfa, 0x23, 0x31, 0x53, 0x65, 0xa1, 0x31, 0x9b, 0xa4, 0xe5, 0x52, 0xa6, 0xd9, 0x8a, 0x36, 274 | 0x82, 0x7a, 0xd4, 0x19, 0xfe, 0xaf, 0xae, 0xed, 0x4b, 0xd8, 0xf7, 0x4b, 0xe1, 0xc9, 0x2e, 0x96, 275 | 0xfc, 0x85, 0xc6, 0x58, 0x64, 0xf8, 0x6c, 0xda, 0xfc, 0x66, 0x1f, 0x80, 0xfc, 0x83, 0xe6, 0x24, 276 | 0x55, 0x28, 0xb4, 0x6d, 0x63, 0x51, 0xf8, 0xea, 0xc1, 0x9f, 0x7d, 0xbb, 0xad, 0xf8, 0x16, 0x45, 277 | 0x86, 0xca, 0x7a, 0x58, 0x44, 0x06, 0xf0, 0x8b, 0xe1, 0x0c, 0xf9, 0x06, 0xd5, 0x8a, 0xd6, 0xcc, 278 | 0x3b, 0x49, 0xf5, 0x4e, 0x47, 0xb1, 0x4a, 0xb4, 0x5d, 0xae, 0x35, 0xb5, 0xbb, 0x72, 0x90, 0x1c, 279 | 0x42, 0xcf, 0xe6, 0x72, 0x29, 0xcc, 0x9a, 0x7d, 0x93, 0xb5, 0x37, 0x0d, 0x2f, 0xa0, 0xed, 0xec, 280 | 0x7e, 0xa8, 0x16, 0x42, 0x77, 0xd7, 0xe0, 0x0a, 0x4b, 0x5b, 0xf0, 0xcb, 0xec, 0xfc, 0xec, 0xe1, 281 | 0x34, 0xe7, 0xfa, 0x71, 0x3d, 0x8d, 0x67, 0xf2, 0x29, 0xd1, 0x72, 0x81, 0x82, 0xbf, 0x60, 0x96, 282 | 0xb8, 0x5f, 0x24, 0x29, 0x16, 0x79, 0x92, 0xcb, 0x65, 0x2a, 0xf2, 0x6a, 0xb6, 0x19, 0x24, 0xae, 283 | 0xdc, 0xb4, 0x69, 0x4e, 0xc7, 0xef, 0x01, 0x00, 0x00, 0xff, 0xff, 0x2a, 0x7e, 0xf4, 0x1b, 0x55, 284 | 0x02, 0x00, 0x00, 285 | } 286 | -------------------------------------------------------------------------------- /pkg/golang/envelope/v0/serialize.go: -------------------------------------------------------------------------------- 1 | package v0 2 | 3 | import ( 4 | "bytes" 5 | 6 | "github.com/tokenized/envelope/pkg/golang/envelope/base" 7 | "github.com/tokenized/envelope/pkg/golang/envelope/v0/protobuf" 8 | "github.com/tokenized/pkg/bitcoin" 9 | 10 | "github.com/golang/protobuf/proto" 11 | "github.com/pkg/errors" 12 | ) 13 | 14 | var ( 15 | ErrNotEnvelope = errors.New("Not an envelope") 16 | ) 17 | 18 | // Serialize writes an OP_RETURN script in the "envelope" format containing the specified data. 19 | func (m *Message) Serialize(buf *bytes.Buffer) error { 20 | // Header 21 | if err := buf.WriteByte(bitcoin.OP_FALSE); err != nil { 22 | return errors.Wrap(err, "Failed to write header") 23 | } 24 | if err := buf.WriteByte(bitcoin.OP_RETURN); err != nil { 25 | return errors.Wrap(err, "Failed to write header") 26 | } 27 | if err := bitcoin.WritePushDataScript(buf, []byte{0xbd, 0x00}); err != nil { 28 | return errors.Wrap(err, "Failed to write envelope protocol ID") 29 | } 30 | 31 | // Protocol 32 | if len(m.payloadProtocol) == 0 { 33 | return errors.New("Payload protocol required") 34 | } 35 | if err := bitcoin.WritePushDataScript(buf, m.payloadProtocol); err != nil { 36 | return errors.Wrap(err, "Failed to write payload protocol") 37 | } 38 | 39 | // Envelope 40 | envelope := protobuf.Envelope{ 41 | Version: m.payloadVersion, 42 | Type: m.payloadType, 43 | Identifier: m.payloadIdentifier, 44 | } 45 | 46 | // Metanet 47 | // Convert to protobuf 48 | if m.metaNet != nil { 49 | envelope.MetaNet = &protobuf.MetaNet{ 50 | Index: m.metaNet.index, 51 | Parent: m.metaNet.parent, 52 | } 53 | } 54 | 55 | // Encrypted payloads 56 | // Convert to protobuf 57 | envelope.EncryptedPayloads = make([]*protobuf.EncryptedPayload, 0, len(m.encryptedPayloads)) 58 | for _, encryptedPayload := range m.encryptedPayloads { 59 | pbEncryptedPayload := protobuf.EncryptedPayload{ 60 | Sender: encryptedPayload.sender, 61 | EncryptionType: encryptedPayload.encryptionType, 62 | } 63 | 64 | // Receivers 65 | pbEncryptedPayload.Receivers = make([]*protobuf.Receiver, 0, len(encryptedPayload.receivers)) 66 | for _, receiver := range encryptedPayload.receivers { 67 | pbEncryptedPayload.Receivers = append(pbEncryptedPayload.Receivers, &protobuf.Receiver{ 68 | Index: receiver.index, 69 | EncryptedKey: receiver.encryptedKey, 70 | }) 71 | } 72 | 73 | // Payload 74 | pbEncryptedPayload.Payload = encryptedPayload.payload 75 | 76 | envelope.EncryptedPayloads = append(envelope.EncryptedPayloads, &pbEncryptedPayload) 77 | } 78 | 79 | // Serialize envelope 80 | data, err := proto.Marshal(&envelope) 81 | if err != nil { 82 | return errors.Wrap(err, "Failed to serialize envelope") 83 | } 84 | 85 | if err := bitcoin.WritePushDataScript(buf, data); err != nil { 86 | return errors.Wrap(err, "Failed to write envelope") 87 | } 88 | 89 | // Public payload 90 | if err := bitcoin.WritePushDataScript(buf, m.payload); err != nil { 91 | return errors.Wrap(err, "Failed to write payload push") 92 | } 93 | 94 | return nil 95 | } 96 | 97 | // Deserialize reads the Message from an OP_RETURN script. 98 | func Deserialize(buf *bytes.Reader) (*Message, error) { 99 | var result Message 100 | 101 | // Protocol ID 102 | var opCode byte 103 | var err error 104 | opCode, result.payloadProtocol, err = bitcoin.ParsePushDataScript(buf) 105 | if err != nil { 106 | return nil, errors.Wrap(err, "parse protocol ID") 107 | } 108 | if len(result.payloadProtocol) == 0 && opCode != bitcoin.OP_FALSE { // Non push data op code 109 | return nil, ErrNotEnvelope 110 | } 111 | 112 | // Envelope 113 | _, envelopeData, err := bitcoin.ParsePushDataScript(buf) 114 | if err != nil { 115 | return nil, errors.Wrap(err, "read MetaNet data") 116 | } 117 | 118 | var envelope protobuf.Envelope 119 | if len(envelopeData) != 0 { 120 | if err = proto.Unmarshal(envelopeData, &envelope); err != nil { 121 | return nil, errors.Wrap(err, "envelope protobuf unmarshaling") 122 | } 123 | } 124 | 125 | result.payloadVersion = envelope.GetVersion() 126 | result.payloadType = envelope.GetType() 127 | result.payloadIdentifier = envelope.GetIdentifier() 128 | 129 | // MetaNet 130 | pbMetaNet := envelope.GetMetaNet() 131 | if pbMetaNet != nil { 132 | result.metaNet = &MetaNet{ 133 | index: pbMetaNet.GetIndex(), 134 | parent: pbMetaNet.GetParent(), 135 | } 136 | } 137 | 138 | // Encrypted payloads 139 | pbEncryptedPayloads := envelope.GetEncryptedPayloads() 140 | result.encryptedPayloads = make([]*EncryptedPayload, 0, len(pbEncryptedPayloads)) 141 | for _, pbEncryptedPayload := range pbEncryptedPayloads { 142 | encryptedPayload := EncryptedPayload{ 143 | encryptionType: pbEncryptedPayload.EncryptionType, 144 | } 145 | 146 | // Sender 147 | encryptedPayload.sender = pbEncryptedPayload.GetSender() 148 | 149 | // Receivers 150 | pbReceivers := pbEncryptedPayload.GetReceivers() 151 | encryptedPayload.receivers = make([]*Receiver, 0, len(pbReceivers)) 152 | for _, pbReceiver := range pbReceivers { 153 | encryptedPayload.receivers = append(encryptedPayload.receivers, &Receiver{ 154 | index: pbReceiver.GetIndex(), 155 | encryptedKey: pbReceiver.GetEncryptedKey(), 156 | }) 157 | } 158 | 159 | // Payload 160 | encryptedPayload.payload = pbEncryptedPayload.GetPayload() 161 | 162 | result.encryptedPayloads = append(result.encryptedPayloads, &encryptedPayload) 163 | } 164 | 165 | // Public payload 166 | _, result.payload, err = bitcoin.ParsePushDataScript(buf) 167 | if err != nil && (errors.Cause(err) != bitcoin.ErrNotPushOp || len(result.payload) == 0) { 168 | return nil, errors.Wrap(err, "read payload") 169 | } 170 | 171 | return &result, nil 172 | } 173 | 174 | // Parse reads the Message from script items. 175 | func Parse(payload bitcoin.ScriptItems) (*Message, error) { 176 | if len(payload) < 2 { 177 | return nil, ErrNotEnvelope 178 | } 179 | 180 | if payload[0].Type != bitcoin.ScriptItemTypePushData { 181 | return nil, errors.Wrap(ErrNotEnvelope, "protocol id not data") 182 | } 183 | 184 | if payload[1].Type != bitcoin.ScriptItemTypePushData { 185 | return nil, errors.Wrap(ErrNotEnvelope, "envelope data not data") 186 | } 187 | 188 | var envelope protobuf.Envelope 189 | if len(payload[1].Data) != 0 { 190 | if err := proto.Unmarshal(payload[1].Data, &envelope); err != nil { 191 | return nil, errors.Wrap(err, "envelope protobuf unmarshaling") 192 | } 193 | } 194 | 195 | result := &Message{ 196 | payloadProtocol: base.ProtocolID(payload[0].Data), 197 | payloadVersion: envelope.GetVersion(), 198 | payloadType: envelope.GetType(), 199 | payloadIdentifier: envelope.GetIdentifier(), 200 | } 201 | 202 | // MetaNet 203 | pbMetaNet := envelope.GetMetaNet() 204 | if pbMetaNet != nil { 205 | result.metaNet = &MetaNet{ 206 | index: pbMetaNet.GetIndex(), 207 | parent: pbMetaNet.GetParent(), 208 | } 209 | } 210 | 211 | // Encrypted payloads 212 | pbEncryptedPayloads := envelope.GetEncryptedPayloads() 213 | result.encryptedPayloads = make([]*EncryptedPayload, 0, len(pbEncryptedPayloads)) 214 | for _, pbEncryptedPayload := range pbEncryptedPayloads { 215 | encryptedPayload := EncryptedPayload{ 216 | encryptionType: pbEncryptedPayload.EncryptionType, 217 | } 218 | 219 | // Sender 220 | encryptedPayload.sender = pbEncryptedPayload.GetSender() 221 | 222 | // Receivers 223 | pbReceivers := pbEncryptedPayload.GetReceivers() 224 | encryptedPayload.receivers = make([]*Receiver, 0, len(pbReceivers)) 225 | for _, pbReceiver := range pbReceivers { 226 | encryptedPayload.receivers = append(encryptedPayload.receivers, &Receiver{ 227 | index: pbReceiver.GetIndex(), 228 | encryptedKey: pbReceiver.GetEncryptedKey(), 229 | }) 230 | } 231 | 232 | // Payload 233 | encryptedPayload.payload = pbEncryptedPayload.GetPayload() 234 | 235 | result.encryptedPayloads = append(result.encryptedPayloads, &encryptedPayload) 236 | } 237 | 238 | // Public payload 239 | if len(payload) > 2 { 240 | if payload[2].Type != bitcoin.ScriptItemTypePushData { 241 | return nil, errors.Wrap(ErrNotEnvelope, "payload not data") 242 | } 243 | result.payload = payload[2].Data 244 | } 245 | 246 | return result, nil 247 | } 248 | -------------------------------------------------------------------------------- /pkg/golang/envelope/v1/models.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import "github.com/tokenized/envelope/pkg/golang/envelope/base" 4 | 5 | const ( 6 | version = uint8(1) 7 | ) 8 | 9 | type Message struct { 10 | payloadProtocols base.ProtocolIDs 11 | payloads [][]byte 12 | } 13 | 14 | // NewMessage creates a message. 15 | func NewMessage(protocols base.ProtocolIDs, payloads [][]byte) *Message { 16 | return &Message{payloadProtocols: protocols, payloads: payloads} 17 | } 18 | 19 | func (m *Message) EnvelopeVersion() uint8 { 20 | return version 21 | } 22 | 23 | func (m *Message) PayloadProtocols() base.ProtocolIDs { 24 | return m.payloadProtocols 25 | } 26 | 27 | func (m *Message) PayloadCount() int { 28 | return len(m.payloads) 29 | } 30 | 31 | func (m *Message) PayloadAt(offset int) []byte { 32 | if offset >= len(m.payloads) { 33 | return nil 34 | } 35 | return m.payloads[offset] 36 | } 37 | 38 | func (m *Message) AddProtocolID(protocolID base.ProtocolID) { 39 | m.payloadProtocols = append(m.payloadProtocols, protocolID) 40 | } 41 | 42 | func (m *Message) AddPayload(payload []byte) { 43 | m.payloads = append(m.payloads, payload) 44 | } 45 | -------------------------------------------------------------------------------- /pkg/golang/envelope/v1/serialize.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "bytes" 5 | 6 | "github.com/tokenized/envelope/pkg/golang/envelope/base" 7 | "github.com/tokenized/pkg/bitcoin" 8 | 9 | "github.com/pkg/errors" 10 | ) 11 | 12 | func Wrap(data base.Data) bitcoin.ScriptItems { 13 | scriptItems := HeaderScriptItems(data.ProtocolIDs) 14 | 15 | // Number of payload push datas 16 | scriptItems = append(scriptItems, bitcoin.PushNumberScriptItem(int64(len(data.Payload)))) 17 | 18 | return append(scriptItems, data.Payload...) 19 | } 20 | 21 | func HeaderScriptItems(protocolIDs base.ProtocolIDs) bitcoin.ScriptItems { 22 | // OP_FALSE, OP_RETURN 23 | result := bitcoin.ScriptItems{bitcoin.NewOpCodeScriptItem(bitcoin.OP_FALSE)} 24 | result = append(result, bitcoin.NewOpCodeScriptItem(bitcoin.OP_RETURN)) 25 | 26 | // Envelope Version 1 Protocol ID 27 | result = append(result, bitcoin.NewPushDataScriptItem([]byte{0xbd, 0x01})) 28 | 29 | // Protocol IDs 30 | result = append(result, bitcoin.PushNumberScriptItem(int64(len(protocolIDs)))) 31 | for _, protocolID := range protocolIDs { 32 | result = append(result, bitcoin.NewPushDataScriptItem(protocolID)) 33 | } 34 | 35 | return result 36 | } 37 | 38 | func WriteHeader(buf *bytes.Buffer, protocolIDs base.ProtocolIDs) error { 39 | // Header 40 | if err := buf.WriteByte(bitcoin.OP_FALSE); err != nil { 41 | return errors.Wrap(err, "op_false") 42 | } 43 | if err := buf.WriteByte(bitcoin.OP_RETURN); err != nil { 44 | return errors.Wrap(err, "op_return") 45 | } 46 | if err := bitcoin.WritePushDataScript(buf, []byte{0xbd, 0x01}); err != nil { 47 | return errors.Wrap(err, "envelope protocol id") 48 | } 49 | 50 | // Payload protocol IDs 51 | if _, err := buf.Write(bitcoin.PushNumberScript(int64(len(protocolIDs)))); err != nil { 52 | return errors.Wrap(err, "payload protocol id count") 53 | } 54 | 55 | // Payload Protocol ID 56 | if len(protocolIDs) == 0 { 57 | return errors.New("Payload protocol required") 58 | } 59 | for i, protocolID := range protocolIDs { 60 | if err := bitcoin.WritePushDataScript(buf, protocolID); err != nil { 61 | return errors.Wrapf(err, "payload protocol id %d", i) 62 | } 63 | } 64 | 65 | return nil 66 | } 67 | 68 | func Parse(buf *bytes.Reader) (base.Data, error) { 69 | protocolIDs, err := ParseProtocolIDs(buf) 70 | if err != nil { 71 | return base.Data{}, errors.Wrap(err, "protocol ids") 72 | } 73 | 74 | // Payloads 75 | payloadCountItem, err := bitcoin.ParseScript(buf) 76 | if err != nil { 77 | return base.Data{}, errors.Wrap(base.ErrInvalidEnvelope, 78 | errors.Wrap(err, "payload count").Error()) 79 | } 80 | 81 | payloadCount, err := bitcoin.ScriptNumberValue(payloadCountItem) 82 | if err != nil { 83 | return base.Data{}, errors.Wrap(base.ErrInvalidEnvelope, 84 | errors.Wrap(err, "payload count value").Error()) 85 | } 86 | if payloadCount < 0 { 87 | return base.Data{}, errors.Wrapf(base.ErrInvalidEnvelope, "negative payload count %d", 88 | payloadCount) 89 | } 90 | 91 | payload, err := bitcoin.ParseScriptItems(buf, int(payloadCount)) 92 | if err != nil { 93 | return base.Data{}, errors.Wrap(err, "payload") 94 | } 95 | 96 | return base.Data{protocolIDs, payload}, nil 97 | } 98 | 99 | func ParseAfterHeader(buf *bytes.Reader) (base.Data, error) { 100 | protocolIDs, err := ParseOnlyProtocolIDs(buf) 101 | if err != nil { 102 | return base.Data{}, errors.Wrap(err, "protocol ids") 103 | } 104 | 105 | // Payloads 106 | payloadCountItem, err := bitcoin.ParseScript(buf) 107 | if err != nil { 108 | return base.Data{}, errors.Wrap(base.ErrInvalidEnvelope, 109 | errors.Wrap(err, "payload count").Error()) 110 | } 111 | 112 | payloadCount, err := bitcoin.ScriptNumberValue(payloadCountItem) 113 | if err != nil { 114 | return base.Data{}, errors.Wrap(base.ErrInvalidEnvelope, 115 | errors.Wrap(err, "payload count value").Error()) 116 | } 117 | if payloadCount < 0 { 118 | return base.Data{}, errors.Wrapf(base.ErrInvalidEnvelope, "negative payload count %d", 119 | payloadCount) 120 | } 121 | 122 | payload, err := bitcoin.ParseScriptItems(buf, int(payloadCount)) 123 | if err != nil { 124 | return base.Data{}, errors.Wrap(err, "payload") 125 | } 126 | 127 | return base.Data{protocolIDs, payload}, nil 128 | } 129 | 130 | func ParseHeader(buf *bytes.Reader) error { 131 | // Header 132 | if buf.Len() < 5 { 133 | return base.ErrNotEnvelope 134 | } 135 | 136 | var b byte 137 | var err error 138 | 139 | b, err = buf.ReadByte() 140 | if err != nil { 141 | return errors.Wrap(err, "read op return") 142 | } 143 | 144 | if b != bitcoin.OP_RETURN { 145 | if b != bitcoin.OP_FALSE { 146 | return base.ErrNotEnvelope 147 | } 148 | 149 | b, err = buf.ReadByte() 150 | if err != nil { 151 | return errors.Wrap(err, "read op return") 152 | } 153 | 154 | if b != bitcoin.OP_RETURN { 155 | return base.ErrNotEnvelope 156 | } 157 | } 158 | 159 | // Envelope Protocol ID 160 | _, protocolID, err := bitcoin.ParsePushDataScript(buf) 161 | if err != nil { 162 | return errors.Wrap(err, "parse protocol ID") 163 | } 164 | if len(protocolID) != 2 { 165 | return base.ErrNotEnvelope 166 | } 167 | if protocolID[0] != 0xbd { 168 | return base.ErrNotEnvelope 169 | } 170 | 171 | if protocolID[1] != 1 { 172 | return base.ErrUnknownVersion 173 | } 174 | 175 | return nil 176 | } 177 | 178 | func ParseProtocolIDs(buf *bytes.Reader) (base.ProtocolIDs, error) { 179 | if err := ParseHeader(buf); err != nil { 180 | return nil, errors.Wrap(err, "header") 181 | } 182 | 183 | // Protocol ID Count 184 | protocolIDCountItem, err := bitcoin.ParseScript(buf) 185 | if err != nil { 186 | return nil, errors.Wrap(base.ErrInvalidEnvelope, 187 | errors.Wrap(err, "protocol ID count").Error()) 188 | } 189 | 190 | protocolIDCount, err := bitcoin.ScriptNumberValue(protocolIDCountItem) 191 | if err != nil { 192 | return nil, errors.Wrap(base.ErrInvalidEnvelope, 193 | errors.Wrap(err, "protocol ID count value").Error()) 194 | } 195 | if protocolIDCount < 0 { 196 | return nil, errors.Wrapf(base.ErrInvalidEnvelope, "negative protocol id count %d", 197 | protocolIDCount) 198 | } 199 | 200 | // Protocol IDs 201 | protocolIDs := make(base.ProtocolIDs, protocolIDCount) 202 | for i := range protocolIDs { 203 | protocolIDItem, err := bitcoin.ParseScript(buf) 204 | if err != nil { 205 | return nil, errors.Wrap(base.ErrInvalidEnvelope, 206 | errors.Wrapf(err, "protocol ID %d", i).Error()) 207 | } 208 | 209 | switch protocolIDItem.Type { 210 | case bitcoin.ScriptItemTypeOpCode: 211 | protocolIDs[i] = base.ProtocolID{protocolIDItem.OpCode} 212 | 213 | case bitcoin.ScriptItemTypePushData: 214 | protocolIDs[i] = base.ProtocolID(protocolIDItem.Data) 215 | 216 | default: 217 | return nil, errors.Wrap(base.ErrInvalidEnvelope, "unknown script item type") 218 | } 219 | } 220 | 221 | return protocolIDs, nil 222 | } 223 | 224 | func ParseOnlyProtocolIDs(buf *bytes.Reader) (base.ProtocolIDs, error) { 225 | // Protocol ID Count 226 | protocolIDCountItem, err := bitcoin.ParseScript(buf) 227 | if err != nil { 228 | return nil, errors.Wrap(base.ErrInvalidEnvelope, 229 | errors.Wrap(err, "protocol ID count").Error()) 230 | } 231 | 232 | protocolIDCount, err := bitcoin.ScriptNumberValue(protocolIDCountItem) 233 | if err != nil { 234 | return nil, errors.Wrap(base.ErrInvalidEnvelope, 235 | errors.Wrap(err, "protocol ID count value").Error()) 236 | } 237 | if protocolIDCount < 0 { 238 | return nil, errors.Wrapf(base.ErrInvalidEnvelope, "negative protocol id count %d", 239 | protocolIDCount) 240 | } 241 | 242 | // Protocol IDs 243 | protocolIDs := make(base.ProtocolIDs, protocolIDCount) 244 | for i := range protocolIDs { 245 | protocolIDItem, err := bitcoin.ParseScript(buf) 246 | if err != nil { 247 | return nil, errors.Wrap(base.ErrInvalidEnvelope, 248 | errors.Wrapf(err, "protocol ID %d", i).Error()) 249 | } 250 | 251 | switch protocolIDItem.Type { 252 | case bitcoin.ScriptItemTypeOpCode: 253 | protocolIDs[i] = base.ProtocolID{protocolIDItem.OpCode} 254 | 255 | case bitcoin.ScriptItemTypePushData: 256 | protocolIDs[i] = base.ProtocolID(protocolIDItem.Data) 257 | 258 | default: 259 | return nil, errors.Wrap(base.ErrInvalidEnvelope, "unknown script item type") 260 | } 261 | } 262 | 263 | return protocolIDs, nil 264 | } 265 | 266 | // Serialize writes an OP_RETURN script in the "envelope" format containing the specified data. 267 | func (m *Message) Serialize(buf *bytes.Buffer) error { 268 | // Header 269 | if err := buf.WriteByte(bitcoin.OP_FALSE); err != nil { 270 | return errors.Wrap(err, "op_false") 271 | } 272 | if err := buf.WriteByte(bitcoin.OP_RETURN); err != nil { 273 | return errors.Wrap(err, "op_return") 274 | } 275 | if err := bitcoin.WritePushDataScript(buf, []byte{0xbd, 0x01}); err != nil { 276 | return errors.Wrap(err, "envelope protocol id") 277 | } 278 | 279 | // Payload protocol IDs 280 | if _, err := buf.Write(bitcoin.PushNumberScript(int64(len(m.payloadProtocols)))); err != nil { 281 | return errors.Wrap(err, "payload protocol id count") 282 | } 283 | 284 | // Payload Protocol ID 285 | if len(m.payloadProtocols) == 0 { 286 | return errors.New("Payload protocol required") 287 | } 288 | for i, protocolID := range m.payloadProtocols { 289 | if err := bitcoin.WritePushDataScript(buf, protocolID); err != nil { 290 | return errors.Wrapf(err, "payload protocol id %d", i) 291 | } 292 | } 293 | 294 | // Number of payload push datas 295 | if _, err := buf.Write(bitcoin.PushNumberScript(int64(len(m.payloads)))); err != nil { 296 | return errors.Wrap(err, "payload count") 297 | } 298 | 299 | // Payloads 300 | for i, payload := range m.payloads { 301 | if err := bitcoin.WritePushDataScript(buf, payload); err != nil { 302 | return errors.Wrapf(err, "payload %d", i) 303 | } 304 | } 305 | 306 | return nil 307 | } 308 | 309 | // Deserialize reads the Message from an OP_RETURN script. 310 | func Deserialize(buf *bytes.Reader) (*Message, error) { 311 | // Protocol IDs 312 | protocolIDCountItem, err := bitcoin.ParseScript(buf) 313 | if err != nil { 314 | return nil, errors.Wrap(base.ErrInvalidEnvelope, 315 | errors.Wrap(err, "protocol ID count").Error()) 316 | } 317 | 318 | protocolIDCount, err := bitcoin.ScriptNumberValue(protocolIDCountItem) 319 | if err != nil { 320 | return nil, errors.Wrap(base.ErrInvalidEnvelope, 321 | errors.Wrap(err, "protocol ID count value").Error()) 322 | } 323 | if protocolIDCount < 0 { 324 | return nil, errors.Wrapf(base.ErrInvalidEnvelope, "negative protocol id count %d", 325 | protocolIDCount) 326 | } 327 | 328 | result := &Message{} 329 | 330 | result.payloadProtocols = make(base.ProtocolIDs, protocolIDCount) 331 | for i := range result.payloadProtocols { 332 | protocolIDItem, err := bitcoin.ParseScript(buf) 333 | if err != nil { 334 | return nil, errors.Wrap(base.ErrInvalidEnvelope, 335 | errors.Wrapf(err, "protocol ID %d", i).Error()) 336 | } 337 | 338 | switch protocolIDItem.Type { 339 | case bitcoin.ScriptItemTypeOpCode: 340 | result.payloadProtocols[i] = base.ProtocolID{protocolIDItem.OpCode} 341 | 342 | case bitcoin.ScriptItemTypePushData: 343 | result.payloadProtocols[i] = base.ProtocolID(protocolIDItem.Data) 344 | 345 | default: 346 | return nil, errors.Wrap(base.ErrInvalidEnvelope, "unknown script item type") 347 | } 348 | } 349 | 350 | // Payloads 351 | payloadCountItem, err := bitcoin.ParseScript(buf) 352 | if err != nil { 353 | return nil, errors.Wrap(base.ErrInvalidEnvelope, errors.Wrap(err, "payload count").Error()) 354 | } 355 | 356 | payloadCount, err := bitcoin.ScriptNumberValue(payloadCountItem) 357 | if err != nil { 358 | return nil, errors.Wrap(base.ErrInvalidEnvelope, 359 | errors.Wrap(err, "payload count value").Error()) 360 | } 361 | if payloadCount < 0 { 362 | return nil, errors.Wrapf(base.ErrInvalidEnvelope, "negative payload count %d", payloadCount) 363 | } 364 | 365 | result.payloads = make([][]byte, payloadCount) 366 | for i := range result.payloads { 367 | payloadItem, err := bitcoin.ParseScript(buf) 368 | if err != nil { 369 | return nil, errors.Wrap(base.ErrInvalidEnvelope, 370 | errors.Wrapf(err, "payload %d", i).Error()) 371 | } 372 | 373 | switch payloadItem.Type { 374 | case bitcoin.ScriptItemTypeOpCode: 375 | result.payloads[i] = []byte{payloadItem.OpCode} 376 | 377 | case bitcoin.ScriptItemTypePushData: 378 | result.payloads[i] = payloadItem.Data 379 | 380 | default: 381 | return nil, errors.Wrap(base.ErrInvalidEnvelope, "unknown script item type") 382 | } 383 | } 384 | 385 | return result, nil 386 | } 387 | -------------------------------------------------------------------------------- /pkg/python/envelope_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: envelope.proto 4 | 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor.FileDescriptor( 17 | name='envelope.proto', 18 | package='protobuf', 19 | syntax='proto3', 20 | serialized_options=b'Z=github.com/tokenized/envelope/pkg/golang/envelope/v0/protobuf', 21 | create_key=_descriptor._internal_create_key, 22 | serialized_pb=b'\n\x0e\x65nvelope.proto\x12\x08protobuf\"\x98\x01\n\x08\x45nvelope\x12\x0f\n\x07Version\x18\x01 \x01(\x04\x12\x0c\n\x04Type\x18\x02 \x01(\x0c\x12\x12\n\nIdentifier\x18\x03 \x01(\x0c\x12\"\n\x07MetaNet\x18\x04 \x01(\x0b\x32\x11.protobuf.MetaNet\x12\x35\n\x11\x45ncryptedPayloads\x18\x05 \x03(\x0b\x32\x1a.protobuf.EncryptedPayload\"(\n\x07MetaNet\x12\r\n\x05Index\x18\x01 \x01(\r\x12\x0e\n\x06Parent\x18\x02 \x01(\x0c\"r\n\x10\x45ncryptedPayload\x12\x0e\n\x06Sender\x18\x01 \x01(\r\x12%\n\tReceivers\x18\x02 \x03(\x0b\x32\x12.protobuf.Receiver\x12\x0f\n\x07Payload\x18\x03 \x01(\x0c\x12\x16\n\x0e\x45ncryptionType\x18\x04 \x01(\r\"/\n\x08Receiver\x12\r\n\x05Index\x18\x01 \x01(\r\x12\x14\n\x0c\x45ncryptedKey\x18\x02 \x01(\x0c\x42?Z=github.com/tokenized/envelope/pkg/golang/envelope/v0/protobufb\x06proto3' 23 | ) 24 | 25 | 26 | 27 | 28 | _ENVELOPE = _descriptor.Descriptor( 29 | name='Envelope', 30 | full_name='protobuf.Envelope', 31 | filename=None, 32 | file=DESCRIPTOR, 33 | containing_type=None, 34 | create_key=_descriptor._internal_create_key, 35 | fields=[ 36 | _descriptor.FieldDescriptor( 37 | name='Version', full_name='protobuf.Envelope.Version', index=0, 38 | number=1, type=4, cpp_type=4, label=1, 39 | has_default_value=False, default_value=0, 40 | message_type=None, enum_type=None, containing_type=None, 41 | is_extension=False, extension_scope=None, 42 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 43 | _descriptor.FieldDescriptor( 44 | name='Type', full_name='protobuf.Envelope.Type', index=1, 45 | number=2, type=12, cpp_type=9, label=1, 46 | has_default_value=False, default_value=b"", 47 | message_type=None, enum_type=None, containing_type=None, 48 | is_extension=False, extension_scope=None, 49 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 50 | _descriptor.FieldDescriptor( 51 | name='Identifier', full_name='protobuf.Envelope.Identifier', index=2, 52 | number=3, type=12, cpp_type=9, label=1, 53 | has_default_value=False, default_value=b"", 54 | message_type=None, enum_type=None, containing_type=None, 55 | is_extension=False, extension_scope=None, 56 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 57 | _descriptor.FieldDescriptor( 58 | name='MetaNet', full_name='protobuf.Envelope.MetaNet', index=3, 59 | number=4, type=11, cpp_type=10, label=1, 60 | has_default_value=False, default_value=None, 61 | message_type=None, enum_type=None, containing_type=None, 62 | is_extension=False, extension_scope=None, 63 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 64 | _descriptor.FieldDescriptor( 65 | name='EncryptedPayloads', full_name='protobuf.Envelope.EncryptedPayloads', index=4, 66 | number=5, type=11, cpp_type=10, label=3, 67 | has_default_value=False, default_value=[], 68 | message_type=None, enum_type=None, containing_type=None, 69 | is_extension=False, extension_scope=None, 70 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 71 | ], 72 | extensions=[ 73 | ], 74 | nested_types=[], 75 | enum_types=[ 76 | ], 77 | serialized_options=None, 78 | is_extendable=False, 79 | syntax='proto3', 80 | extension_ranges=[], 81 | oneofs=[ 82 | ], 83 | serialized_start=29, 84 | serialized_end=181, 85 | ) 86 | 87 | 88 | _METANET = _descriptor.Descriptor( 89 | name='MetaNet', 90 | full_name='protobuf.MetaNet', 91 | filename=None, 92 | file=DESCRIPTOR, 93 | containing_type=None, 94 | create_key=_descriptor._internal_create_key, 95 | fields=[ 96 | _descriptor.FieldDescriptor( 97 | name='Index', full_name='protobuf.MetaNet.Index', index=0, 98 | number=1, type=13, cpp_type=3, label=1, 99 | has_default_value=False, default_value=0, 100 | message_type=None, enum_type=None, containing_type=None, 101 | is_extension=False, extension_scope=None, 102 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 103 | _descriptor.FieldDescriptor( 104 | name='Parent', full_name='protobuf.MetaNet.Parent', index=1, 105 | number=2, type=12, cpp_type=9, label=1, 106 | has_default_value=False, default_value=b"", 107 | message_type=None, enum_type=None, containing_type=None, 108 | is_extension=False, extension_scope=None, 109 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 110 | ], 111 | extensions=[ 112 | ], 113 | nested_types=[], 114 | enum_types=[ 115 | ], 116 | serialized_options=None, 117 | is_extendable=False, 118 | syntax='proto3', 119 | extension_ranges=[], 120 | oneofs=[ 121 | ], 122 | serialized_start=183, 123 | serialized_end=223, 124 | ) 125 | 126 | 127 | _ENCRYPTEDPAYLOAD = _descriptor.Descriptor( 128 | name='EncryptedPayload', 129 | full_name='protobuf.EncryptedPayload', 130 | filename=None, 131 | file=DESCRIPTOR, 132 | containing_type=None, 133 | create_key=_descriptor._internal_create_key, 134 | fields=[ 135 | _descriptor.FieldDescriptor( 136 | name='Sender', full_name='protobuf.EncryptedPayload.Sender', index=0, 137 | number=1, type=13, cpp_type=3, label=1, 138 | has_default_value=False, default_value=0, 139 | message_type=None, enum_type=None, containing_type=None, 140 | is_extension=False, extension_scope=None, 141 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 142 | _descriptor.FieldDescriptor( 143 | name='Receivers', full_name='protobuf.EncryptedPayload.Receivers', index=1, 144 | number=2, type=11, cpp_type=10, label=3, 145 | has_default_value=False, default_value=[], 146 | message_type=None, enum_type=None, containing_type=None, 147 | is_extension=False, extension_scope=None, 148 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 149 | _descriptor.FieldDescriptor( 150 | name='Payload', full_name='protobuf.EncryptedPayload.Payload', index=2, 151 | number=3, type=12, cpp_type=9, label=1, 152 | has_default_value=False, default_value=b"", 153 | message_type=None, enum_type=None, containing_type=None, 154 | is_extension=False, extension_scope=None, 155 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 156 | _descriptor.FieldDescriptor( 157 | name='EncryptionType', full_name='protobuf.EncryptedPayload.EncryptionType', index=3, 158 | number=4, type=13, cpp_type=3, label=1, 159 | has_default_value=False, default_value=0, 160 | message_type=None, enum_type=None, containing_type=None, 161 | is_extension=False, extension_scope=None, 162 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 163 | ], 164 | extensions=[ 165 | ], 166 | nested_types=[], 167 | enum_types=[ 168 | ], 169 | serialized_options=None, 170 | is_extendable=False, 171 | syntax='proto3', 172 | extension_ranges=[], 173 | oneofs=[ 174 | ], 175 | serialized_start=225, 176 | serialized_end=339, 177 | ) 178 | 179 | 180 | _RECEIVER = _descriptor.Descriptor( 181 | name='Receiver', 182 | full_name='protobuf.Receiver', 183 | filename=None, 184 | file=DESCRIPTOR, 185 | containing_type=None, 186 | create_key=_descriptor._internal_create_key, 187 | fields=[ 188 | _descriptor.FieldDescriptor( 189 | name='Index', full_name='protobuf.Receiver.Index', index=0, 190 | number=1, type=13, cpp_type=3, label=1, 191 | has_default_value=False, default_value=0, 192 | message_type=None, enum_type=None, containing_type=None, 193 | is_extension=False, extension_scope=None, 194 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 195 | _descriptor.FieldDescriptor( 196 | name='EncryptedKey', full_name='protobuf.Receiver.EncryptedKey', index=1, 197 | number=2, type=12, cpp_type=9, label=1, 198 | has_default_value=False, default_value=b"", 199 | message_type=None, enum_type=None, containing_type=None, 200 | is_extension=False, extension_scope=None, 201 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 202 | ], 203 | extensions=[ 204 | ], 205 | nested_types=[], 206 | enum_types=[ 207 | ], 208 | serialized_options=None, 209 | is_extendable=False, 210 | syntax='proto3', 211 | extension_ranges=[], 212 | oneofs=[ 213 | ], 214 | serialized_start=341, 215 | serialized_end=388, 216 | ) 217 | 218 | _ENVELOPE.fields_by_name['MetaNet'].message_type = _METANET 219 | _ENVELOPE.fields_by_name['EncryptedPayloads'].message_type = _ENCRYPTEDPAYLOAD 220 | _ENCRYPTEDPAYLOAD.fields_by_name['Receivers'].message_type = _RECEIVER 221 | DESCRIPTOR.message_types_by_name['Envelope'] = _ENVELOPE 222 | DESCRIPTOR.message_types_by_name['MetaNet'] = _METANET 223 | DESCRIPTOR.message_types_by_name['EncryptedPayload'] = _ENCRYPTEDPAYLOAD 224 | DESCRIPTOR.message_types_by_name['Receiver'] = _RECEIVER 225 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 226 | 227 | Envelope = _reflection.GeneratedProtocolMessageType('Envelope', (_message.Message,), { 228 | 'DESCRIPTOR' : _ENVELOPE, 229 | '__module__' : 'envelope_pb2' 230 | # @@protoc_insertion_point(class_scope:protobuf.Envelope) 231 | }) 232 | _sym_db.RegisterMessage(Envelope) 233 | 234 | MetaNet = _reflection.GeneratedProtocolMessageType('MetaNet', (_message.Message,), { 235 | 'DESCRIPTOR' : _METANET, 236 | '__module__' : 'envelope_pb2' 237 | # @@protoc_insertion_point(class_scope:protobuf.MetaNet) 238 | }) 239 | _sym_db.RegisterMessage(MetaNet) 240 | 241 | EncryptedPayload = _reflection.GeneratedProtocolMessageType('EncryptedPayload', (_message.Message,), { 242 | 'DESCRIPTOR' : _ENCRYPTEDPAYLOAD, 243 | '__module__' : 'envelope_pb2' 244 | # @@protoc_insertion_point(class_scope:protobuf.EncryptedPayload) 245 | }) 246 | _sym_db.RegisterMessage(EncryptedPayload) 247 | 248 | Receiver = _reflection.GeneratedProtocolMessageType('Receiver', (_message.Message,), { 249 | 'DESCRIPTOR' : _RECEIVER, 250 | '__module__' : 'envelope_pb2' 251 | # @@protoc_insertion_point(class_scope:protobuf.Receiver) 252 | }) 253 | _sym_db.RegisterMessage(Receiver) 254 | 255 | 256 | DESCRIPTOR._options = None 257 | # @@protoc_insertion_point(module_scope) 258 | -------------------------------------------------------------------------------- /pkg/typescript/v0/protobuf.js: -------------------------------------------------------------------------------- 1 | // source: envelope.proto 2 | /** 3 | * @fileoverview 4 | * @enhanceable 5 | * @suppress {messageConventions} JS Compiler reports an error if a variable or 6 | * field starts with 'MSG_' and isn't a translatable message. 7 | * @public 8 | */ 9 | // GENERATED CODE -- DO NOT EDIT! 10 | 11 | 12 | goog.provide('proto.protobuf.EncryptedPayload'); 13 | goog.provide('proto.protobuf.Envelope'); 14 | goog.provide('proto.protobuf.MetaNet'); 15 | goog.provide('proto.protobuf.Receiver'); 16 | 17 | goog.require('jspb.BinaryReader'); 18 | goog.require('jspb.BinaryWriter'); 19 | goog.require('jspb.Message'); 20 | 21 | /** 22 | * Generated by JsPbCodeGenerator. 23 | * @param {Array=} opt_data Optional initial data array, typically from a 24 | * server response, or constructed directly in Javascript. The array is used 25 | * in place and becomes part of the constructed object. It is not cloned. 26 | * If no data is provided, the constructed object will be empty, but still 27 | * valid. 28 | * @extends {jspb.Message} 29 | * @constructor 30 | */ 31 | proto.protobuf.Envelope = function(opt_data) { 32 | jspb.Message.initialize(this, opt_data, 0, -1, proto.protobuf.Envelope.repeatedFields_, null); 33 | }; 34 | goog.inherits(proto.protobuf.Envelope, jspb.Message); 35 | if (goog.DEBUG && !COMPILED) { 36 | /** 37 | * @public 38 | * @override 39 | */ 40 | proto.protobuf.Envelope.displayName = 'proto.protobuf.Envelope'; 41 | } 42 | /** 43 | * Generated by JsPbCodeGenerator. 44 | * @param {Array=} opt_data Optional initial data array, typically from a 45 | * server response, or constructed directly in Javascript. The array is used 46 | * in place and becomes part of the constructed object. It is not cloned. 47 | * If no data is provided, the constructed object will be empty, but still 48 | * valid. 49 | * @extends {jspb.Message} 50 | * @constructor 51 | */ 52 | proto.protobuf.MetaNet = function(opt_data) { 53 | jspb.Message.initialize(this, opt_data, 0, -1, null, null); 54 | }; 55 | goog.inherits(proto.protobuf.MetaNet, jspb.Message); 56 | if (goog.DEBUG && !COMPILED) { 57 | /** 58 | * @public 59 | * @override 60 | */ 61 | proto.protobuf.MetaNet.displayName = 'proto.protobuf.MetaNet'; 62 | } 63 | /** 64 | * Generated by JsPbCodeGenerator. 65 | * @param {Array=} opt_data Optional initial data array, typically from a 66 | * server response, or constructed directly in Javascript. The array is used 67 | * in place and becomes part of the constructed object. It is not cloned. 68 | * If no data is provided, the constructed object will be empty, but still 69 | * valid. 70 | * @extends {jspb.Message} 71 | * @constructor 72 | */ 73 | proto.protobuf.EncryptedPayload = function(opt_data) { 74 | jspb.Message.initialize(this, opt_data, 0, -1, proto.protobuf.EncryptedPayload.repeatedFields_, null); 75 | }; 76 | goog.inherits(proto.protobuf.EncryptedPayload, jspb.Message); 77 | if (goog.DEBUG && !COMPILED) { 78 | /** 79 | * @public 80 | * @override 81 | */ 82 | proto.protobuf.EncryptedPayload.displayName = 'proto.protobuf.EncryptedPayload'; 83 | } 84 | /** 85 | * Generated by JsPbCodeGenerator. 86 | * @param {Array=} opt_data Optional initial data array, typically from a 87 | * server response, or constructed directly in Javascript. The array is used 88 | * in place and becomes part of the constructed object. It is not cloned. 89 | * If no data is provided, the constructed object will be empty, but still 90 | * valid. 91 | * @extends {jspb.Message} 92 | * @constructor 93 | */ 94 | proto.protobuf.Receiver = function(opt_data) { 95 | jspb.Message.initialize(this, opt_data, 0, -1, null, null); 96 | }; 97 | goog.inherits(proto.protobuf.Receiver, jspb.Message); 98 | if (goog.DEBUG && !COMPILED) { 99 | /** 100 | * @public 101 | * @override 102 | */ 103 | proto.protobuf.Receiver.displayName = 'proto.protobuf.Receiver'; 104 | } 105 | 106 | /** 107 | * List of repeated fields within this message type. 108 | * @private {!Array} 109 | * @const 110 | */ 111 | proto.protobuf.Envelope.repeatedFields_ = [5]; 112 | 113 | 114 | 115 | if (jspb.Message.GENERATE_TO_OBJECT) { 116 | /** 117 | * Creates an object representation of this proto. 118 | * Field names that are reserved in JavaScript and will be renamed to pb_name. 119 | * Optional fields that are not set will be set to undefined. 120 | * To access a reserved field use, foo.pb_, eg, foo.pb_default. 121 | * For the list of reserved names please see: 122 | * net/proto2/compiler/js/internal/generator.cc#kKeyword. 123 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the 124 | * JSPB instance for transitional soy proto support: 125 | * http://goto/soy-param-migration 126 | * @return {!Object} 127 | */ 128 | proto.protobuf.Envelope.prototype.toObject = function(opt_includeInstance) { 129 | return proto.protobuf.Envelope.toObject(opt_includeInstance, this); 130 | }; 131 | 132 | 133 | /** 134 | * Static version of the {@see toObject} method. 135 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include 136 | * the JSPB instance for transitional soy proto support: 137 | * http://goto/soy-param-migration 138 | * @param {!proto.protobuf.Envelope} msg The msg instance to transform. 139 | * @return {!Object} 140 | * @suppress {unusedLocalVariables} f is only used for nested messages 141 | */ 142 | proto.protobuf.Envelope.toObject = function(includeInstance, msg) { 143 | var f, obj = { 144 | version: jspb.Message.getFieldWithDefault(msg, 1, 0), 145 | type: msg.getType_asB64(), 146 | identifier: msg.getIdentifier_asB64(), 147 | metanet: (f = msg.getMetanet()) && proto.protobuf.MetaNet.toObject(includeInstance, f), 148 | encryptedpayloadsList: jspb.Message.toObjectList(msg.getEncryptedpayloadsList(), 149 | proto.protobuf.EncryptedPayload.toObject, includeInstance) 150 | }; 151 | 152 | if (includeInstance) { 153 | obj.$jspbMessageInstance = msg; 154 | } 155 | return obj; 156 | }; 157 | } 158 | 159 | 160 | /** 161 | * Deserializes binary data (in protobuf wire format). 162 | * @param {jspb.ByteSource} bytes The bytes to deserialize. 163 | * @return {!proto.protobuf.Envelope} 164 | */ 165 | proto.protobuf.Envelope.deserializeBinary = function(bytes) { 166 | var reader = new jspb.BinaryReader(bytes); 167 | var msg = new proto.protobuf.Envelope; 168 | return proto.protobuf.Envelope.deserializeBinaryFromReader(msg, reader); 169 | }; 170 | 171 | 172 | /** 173 | * Deserializes binary data (in protobuf wire format) from the 174 | * given reader into the given message object. 175 | * @param {!proto.protobuf.Envelope} msg The message object to deserialize into. 176 | * @param {!jspb.BinaryReader} reader The BinaryReader to use. 177 | * @return {!proto.protobuf.Envelope} 178 | */ 179 | proto.protobuf.Envelope.deserializeBinaryFromReader = function(msg, reader) { 180 | while (reader.nextField()) { 181 | if (reader.isEndGroup()) { 182 | break; 183 | } 184 | var field = reader.getFieldNumber(); 185 | switch (field) { 186 | case 1: 187 | var value = /** @type {number} */ (reader.readUint64()); 188 | msg.setVersion(value); 189 | break; 190 | case 2: 191 | var value = /** @type {!Uint8Array} */ (reader.readBytes()); 192 | msg.setType(value); 193 | break; 194 | case 3: 195 | var value = /** @type {!Uint8Array} */ (reader.readBytes()); 196 | msg.setIdentifier(value); 197 | break; 198 | case 4: 199 | var value = new proto.protobuf.MetaNet; 200 | reader.readMessage(value,proto.protobuf.MetaNet.deserializeBinaryFromReader); 201 | msg.setMetanet(value); 202 | break; 203 | case 5: 204 | var value = new proto.protobuf.EncryptedPayload; 205 | reader.readMessage(value,proto.protobuf.EncryptedPayload.deserializeBinaryFromReader); 206 | msg.addEncryptedpayloads(value); 207 | break; 208 | default: 209 | reader.skipField(); 210 | break; 211 | } 212 | } 213 | return msg; 214 | }; 215 | 216 | 217 | /** 218 | * Serializes the message to binary data (in protobuf wire format). 219 | * @return {!Uint8Array} 220 | */ 221 | proto.protobuf.Envelope.prototype.serializeBinary = function() { 222 | var writer = new jspb.BinaryWriter(); 223 | proto.protobuf.Envelope.serializeBinaryToWriter(this, writer); 224 | return writer.getResultBuffer(); 225 | }; 226 | 227 | 228 | /** 229 | * Serializes the given message to binary data (in protobuf wire 230 | * format), writing to the given BinaryWriter. 231 | * @param {!proto.protobuf.Envelope} message 232 | * @param {!jspb.BinaryWriter} writer 233 | * @suppress {unusedLocalVariables} f is only used for nested messages 234 | */ 235 | proto.protobuf.Envelope.serializeBinaryToWriter = function(message, writer) { 236 | var f = undefined; 237 | f = message.getVersion(); 238 | if (f !== 0) { 239 | writer.writeUint64( 240 | 1, 241 | f 242 | ); 243 | } 244 | f = message.getType_asU8(); 245 | if (f.length > 0) { 246 | writer.writeBytes( 247 | 2, 248 | f 249 | ); 250 | } 251 | f = message.getIdentifier_asU8(); 252 | if (f.length > 0) { 253 | writer.writeBytes( 254 | 3, 255 | f 256 | ); 257 | } 258 | f = message.getMetanet(); 259 | if (f != null) { 260 | writer.writeMessage( 261 | 4, 262 | f, 263 | proto.protobuf.MetaNet.serializeBinaryToWriter 264 | ); 265 | } 266 | f = message.getEncryptedpayloadsList(); 267 | if (f.length > 0) { 268 | writer.writeRepeatedMessage( 269 | 5, 270 | f, 271 | proto.protobuf.EncryptedPayload.serializeBinaryToWriter 272 | ); 273 | } 274 | }; 275 | 276 | 277 | /** 278 | * optional uint64 Version = 1; 279 | * @return {number} 280 | */ 281 | proto.protobuf.Envelope.prototype.getVersion = function() { 282 | return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); 283 | }; 284 | 285 | 286 | /** 287 | * @param {number} value 288 | * @return {!proto.protobuf.Envelope} returns this 289 | */ 290 | proto.protobuf.Envelope.prototype.setVersion = function(value) { 291 | return jspb.Message.setProto3IntField(this, 1, value); 292 | }; 293 | 294 | 295 | /** 296 | * optional bytes Type = 2; 297 | * @return {!(string|Uint8Array)} 298 | */ 299 | proto.protobuf.Envelope.prototype.getType = function() { 300 | return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 2, "")); 301 | }; 302 | 303 | 304 | /** 305 | * optional bytes Type = 2; 306 | * This is a type-conversion wrapper around `getType()` 307 | * @return {string} 308 | */ 309 | proto.protobuf.Envelope.prototype.getType_asB64 = function() { 310 | return /** @type {string} */ (jspb.Message.bytesAsB64( 311 | this.getType())); 312 | }; 313 | 314 | 315 | /** 316 | * optional bytes Type = 2; 317 | * Note that Uint8Array is not supported on all browsers. 318 | * @see http://caniuse.com/Uint8Array 319 | * This is a type-conversion wrapper around `getType()` 320 | * @return {!Uint8Array} 321 | */ 322 | proto.protobuf.Envelope.prototype.getType_asU8 = function() { 323 | return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( 324 | this.getType())); 325 | }; 326 | 327 | 328 | /** 329 | * @param {!(string|Uint8Array)} value 330 | * @return {!proto.protobuf.Envelope} returns this 331 | */ 332 | proto.protobuf.Envelope.prototype.setType = function(value) { 333 | return jspb.Message.setProto3BytesField(this, 2, value); 334 | }; 335 | 336 | 337 | /** 338 | * optional bytes Identifier = 3; 339 | * @return {!(string|Uint8Array)} 340 | */ 341 | proto.protobuf.Envelope.prototype.getIdentifier = function() { 342 | return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 3, "")); 343 | }; 344 | 345 | 346 | /** 347 | * optional bytes Identifier = 3; 348 | * This is a type-conversion wrapper around `getIdentifier()` 349 | * @return {string} 350 | */ 351 | proto.protobuf.Envelope.prototype.getIdentifier_asB64 = function() { 352 | return /** @type {string} */ (jspb.Message.bytesAsB64( 353 | this.getIdentifier())); 354 | }; 355 | 356 | 357 | /** 358 | * optional bytes Identifier = 3; 359 | * Note that Uint8Array is not supported on all browsers. 360 | * @see http://caniuse.com/Uint8Array 361 | * This is a type-conversion wrapper around `getIdentifier()` 362 | * @return {!Uint8Array} 363 | */ 364 | proto.protobuf.Envelope.prototype.getIdentifier_asU8 = function() { 365 | return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( 366 | this.getIdentifier())); 367 | }; 368 | 369 | 370 | /** 371 | * @param {!(string|Uint8Array)} value 372 | * @return {!proto.protobuf.Envelope} returns this 373 | */ 374 | proto.protobuf.Envelope.prototype.setIdentifier = function(value) { 375 | return jspb.Message.setProto3BytesField(this, 3, value); 376 | }; 377 | 378 | 379 | /** 380 | * optional MetaNet MetaNet = 4; 381 | * @return {?proto.protobuf.MetaNet} 382 | */ 383 | proto.protobuf.Envelope.prototype.getMetanet = function() { 384 | return /** @type{?proto.protobuf.MetaNet} */ ( 385 | jspb.Message.getWrapperField(this, proto.protobuf.MetaNet, 4)); 386 | }; 387 | 388 | 389 | /** 390 | * @param {?proto.protobuf.MetaNet|undefined} value 391 | * @return {!proto.protobuf.Envelope} returns this 392 | */ 393 | proto.protobuf.Envelope.prototype.setMetanet = function(value) { 394 | return jspb.Message.setWrapperField(this, 4, value); 395 | }; 396 | 397 | 398 | /** 399 | * Clears the message field making it undefined. 400 | * @return {!proto.protobuf.Envelope} returns this 401 | */ 402 | proto.protobuf.Envelope.prototype.clearMetanet = function() { 403 | return this.setMetanet(undefined); 404 | }; 405 | 406 | 407 | /** 408 | * Returns whether this field is set. 409 | * @return {boolean} 410 | */ 411 | proto.protobuf.Envelope.prototype.hasMetanet = function() { 412 | return jspb.Message.getField(this, 4) != null; 413 | }; 414 | 415 | 416 | /** 417 | * repeated EncryptedPayload EncryptedPayloads = 5; 418 | * @return {!Array} 419 | */ 420 | proto.protobuf.Envelope.prototype.getEncryptedpayloadsList = function() { 421 | return /** @type{!Array} */ ( 422 | jspb.Message.getRepeatedWrapperField(this, proto.protobuf.EncryptedPayload, 5)); 423 | }; 424 | 425 | 426 | /** 427 | * @param {!Array} value 428 | * @return {!proto.protobuf.Envelope} returns this 429 | */ 430 | proto.protobuf.Envelope.prototype.setEncryptedpayloadsList = function(value) { 431 | return jspb.Message.setRepeatedWrapperField(this, 5, value); 432 | }; 433 | 434 | 435 | /** 436 | * @param {!proto.protobuf.EncryptedPayload=} opt_value 437 | * @param {number=} opt_index 438 | * @return {!proto.protobuf.EncryptedPayload} 439 | */ 440 | proto.protobuf.Envelope.prototype.addEncryptedpayloads = function(opt_value, opt_index) { 441 | return jspb.Message.addToRepeatedWrapperField(this, 5, opt_value, proto.protobuf.EncryptedPayload, opt_index); 442 | }; 443 | 444 | 445 | /** 446 | * Clears the list making it empty but non-null. 447 | * @return {!proto.protobuf.Envelope} returns this 448 | */ 449 | proto.protobuf.Envelope.prototype.clearEncryptedpayloadsList = function() { 450 | return this.setEncryptedpayloadsList([]); 451 | }; 452 | 453 | 454 | 455 | 456 | 457 | if (jspb.Message.GENERATE_TO_OBJECT) { 458 | /** 459 | * Creates an object representation of this proto. 460 | * Field names that are reserved in JavaScript and will be renamed to pb_name. 461 | * Optional fields that are not set will be set to undefined. 462 | * To access a reserved field use, foo.pb_, eg, foo.pb_default. 463 | * For the list of reserved names please see: 464 | * net/proto2/compiler/js/internal/generator.cc#kKeyword. 465 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the 466 | * JSPB instance for transitional soy proto support: 467 | * http://goto/soy-param-migration 468 | * @return {!Object} 469 | */ 470 | proto.protobuf.MetaNet.prototype.toObject = function(opt_includeInstance) { 471 | return proto.protobuf.MetaNet.toObject(opt_includeInstance, this); 472 | }; 473 | 474 | 475 | /** 476 | * Static version of the {@see toObject} method. 477 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include 478 | * the JSPB instance for transitional soy proto support: 479 | * http://goto/soy-param-migration 480 | * @param {!proto.protobuf.MetaNet} msg The msg instance to transform. 481 | * @return {!Object} 482 | * @suppress {unusedLocalVariables} f is only used for nested messages 483 | */ 484 | proto.protobuf.MetaNet.toObject = function(includeInstance, msg) { 485 | var f, obj = { 486 | index: jspb.Message.getFieldWithDefault(msg, 1, 0), 487 | parent: msg.getParent_asB64() 488 | }; 489 | 490 | if (includeInstance) { 491 | obj.$jspbMessageInstance = msg; 492 | } 493 | return obj; 494 | }; 495 | } 496 | 497 | 498 | /** 499 | * Deserializes binary data (in protobuf wire format). 500 | * @param {jspb.ByteSource} bytes The bytes to deserialize. 501 | * @return {!proto.protobuf.MetaNet} 502 | */ 503 | proto.protobuf.MetaNet.deserializeBinary = function(bytes) { 504 | var reader = new jspb.BinaryReader(bytes); 505 | var msg = new proto.protobuf.MetaNet; 506 | return proto.protobuf.MetaNet.deserializeBinaryFromReader(msg, reader); 507 | }; 508 | 509 | 510 | /** 511 | * Deserializes binary data (in protobuf wire format) from the 512 | * given reader into the given message object. 513 | * @param {!proto.protobuf.MetaNet} msg The message object to deserialize into. 514 | * @param {!jspb.BinaryReader} reader The BinaryReader to use. 515 | * @return {!proto.protobuf.MetaNet} 516 | */ 517 | proto.protobuf.MetaNet.deserializeBinaryFromReader = function(msg, reader) { 518 | while (reader.nextField()) { 519 | if (reader.isEndGroup()) { 520 | break; 521 | } 522 | var field = reader.getFieldNumber(); 523 | switch (field) { 524 | case 1: 525 | var value = /** @type {number} */ (reader.readUint32()); 526 | msg.setIndex(value); 527 | break; 528 | case 2: 529 | var value = /** @type {!Uint8Array} */ (reader.readBytes()); 530 | msg.setParent(value); 531 | break; 532 | default: 533 | reader.skipField(); 534 | break; 535 | } 536 | } 537 | return msg; 538 | }; 539 | 540 | 541 | /** 542 | * Serializes the message to binary data (in protobuf wire format). 543 | * @return {!Uint8Array} 544 | */ 545 | proto.protobuf.MetaNet.prototype.serializeBinary = function() { 546 | var writer = new jspb.BinaryWriter(); 547 | proto.protobuf.MetaNet.serializeBinaryToWriter(this, writer); 548 | return writer.getResultBuffer(); 549 | }; 550 | 551 | 552 | /** 553 | * Serializes the given message to binary data (in protobuf wire 554 | * format), writing to the given BinaryWriter. 555 | * @param {!proto.protobuf.MetaNet} message 556 | * @param {!jspb.BinaryWriter} writer 557 | * @suppress {unusedLocalVariables} f is only used for nested messages 558 | */ 559 | proto.protobuf.MetaNet.serializeBinaryToWriter = function(message, writer) { 560 | var f = undefined; 561 | f = message.getIndex(); 562 | if (f !== 0) { 563 | writer.writeUint32( 564 | 1, 565 | f 566 | ); 567 | } 568 | f = message.getParent_asU8(); 569 | if (f.length > 0) { 570 | writer.writeBytes( 571 | 2, 572 | f 573 | ); 574 | } 575 | }; 576 | 577 | 578 | /** 579 | * optional uint32 Index = 1; 580 | * @return {number} 581 | */ 582 | proto.protobuf.MetaNet.prototype.getIndex = function() { 583 | return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); 584 | }; 585 | 586 | 587 | /** 588 | * @param {number} value 589 | * @return {!proto.protobuf.MetaNet} returns this 590 | */ 591 | proto.protobuf.MetaNet.prototype.setIndex = function(value) { 592 | return jspb.Message.setProto3IntField(this, 1, value); 593 | }; 594 | 595 | 596 | /** 597 | * optional bytes Parent = 2; 598 | * @return {!(string|Uint8Array)} 599 | */ 600 | proto.protobuf.MetaNet.prototype.getParent = function() { 601 | return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 2, "")); 602 | }; 603 | 604 | 605 | /** 606 | * optional bytes Parent = 2; 607 | * This is a type-conversion wrapper around `getParent()` 608 | * @return {string} 609 | */ 610 | proto.protobuf.MetaNet.prototype.getParent_asB64 = function() { 611 | return /** @type {string} */ (jspb.Message.bytesAsB64( 612 | this.getParent())); 613 | }; 614 | 615 | 616 | /** 617 | * optional bytes Parent = 2; 618 | * Note that Uint8Array is not supported on all browsers. 619 | * @see http://caniuse.com/Uint8Array 620 | * This is a type-conversion wrapper around `getParent()` 621 | * @return {!Uint8Array} 622 | */ 623 | proto.protobuf.MetaNet.prototype.getParent_asU8 = function() { 624 | return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( 625 | this.getParent())); 626 | }; 627 | 628 | 629 | /** 630 | * @param {!(string|Uint8Array)} value 631 | * @return {!proto.protobuf.MetaNet} returns this 632 | */ 633 | proto.protobuf.MetaNet.prototype.setParent = function(value) { 634 | return jspb.Message.setProto3BytesField(this, 2, value); 635 | }; 636 | 637 | 638 | 639 | /** 640 | * List of repeated fields within this message type. 641 | * @private {!Array} 642 | * @const 643 | */ 644 | proto.protobuf.EncryptedPayload.repeatedFields_ = [2]; 645 | 646 | 647 | 648 | if (jspb.Message.GENERATE_TO_OBJECT) { 649 | /** 650 | * Creates an object representation of this proto. 651 | * Field names that are reserved in JavaScript and will be renamed to pb_name. 652 | * Optional fields that are not set will be set to undefined. 653 | * To access a reserved field use, foo.pb_, eg, foo.pb_default. 654 | * For the list of reserved names please see: 655 | * net/proto2/compiler/js/internal/generator.cc#kKeyword. 656 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the 657 | * JSPB instance for transitional soy proto support: 658 | * http://goto/soy-param-migration 659 | * @return {!Object} 660 | */ 661 | proto.protobuf.EncryptedPayload.prototype.toObject = function(opt_includeInstance) { 662 | return proto.protobuf.EncryptedPayload.toObject(opt_includeInstance, this); 663 | }; 664 | 665 | 666 | /** 667 | * Static version of the {@see toObject} method. 668 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include 669 | * the JSPB instance for transitional soy proto support: 670 | * http://goto/soy-param-migration 671 | * @param {!proto.protobuf.EncryptedPayload} msg The msg instance to transform. 672 | * @return {!Object} 673 | * @suppress {unusedLocalVariables} f is only used for nested messages 674 | */ 675 | proto.protobuf.EncryptedPayload.toObject = function(includeInstance, msg) { 676 | var f, obj = { 677 | sender: jspb.Message.getFieldWithDefault(msg, 1, 0), 678 | receiversList: jspb.Message.toObjectList(msg.getReceiversList(), 679 | proto.protobuf.Receiver.toObject, includeInstance), 680 | payload: msg.getPayload_asB64(), 681 | encryptiontype: jspb.Message.getFieldWithDefault(msg, 4, 0) 682 | }; 683 | 684 | if (includeInstance) { 685 | obj.$jspbMessageInstance = msg; 686 | } 687 | return obj; 688 | }; 689 | } 690 | 691 | 692 | /** 693 | * Deserializes binary data (in protobuf wire format). 694 | * @param {jspb.ByteSource} bytes The bytes to deserialize. 695 | * @return {!proto.protobuf.EncryptedPayload} 696 | */ 697 | proto.protobuf.EncryptedPayload.deserializeBinary = function(bytes) { 698 | var reader = new jspb.BinaryReader(bytes); 699 | var msg = new proto.protobuf.EncryptedPayload; 700 | return proto.protobuf.EncryptedPayload.deserializeBinaryFromReader(msg, reader); 701 | }; 702 | 703 | 704 | /** 705 | * Deserializes binary data (in protobuf wire format) from the 706 | * given reader into the given message object. 707 | * @param {!proto.protobuf.EncryptedPayload} msg The message object to deserialize into. 708 | * @param {!jspb.BinaryReader} reader The BinaryReader to use. 709 | * @return {!proto.protobuf.EncryptedPayload} 710 | */ 711 | proto.protobuf.EncryptedPayload.deserializeBinaryFromReader = function(msg, reader) { 712 | while (reader.nextField()) { 713 | if (reader.isEndGroup()) { 714 | break; 715 | } 716 | var field = reader.getFieldNumber(); 717 | switch (field) { 718 | case 1: 719 | var value = /** @type {number} */ (reader.readUint32()); 720 | msg.setSender(value); 721 | break; 722 | case 2: 723 | var value = new proto.protobuf.Receiver; 724 | reader.readMessage(value,proto.protobuf.Receiver.deserializeBinaryFromReader); 725 | msg.addReceivers(value); 726 | break; 727 | case 3: 728 | var value = /** @type {!Uint8Array} */ (reader.readBytes()); 729 | msg.setPayload(value); 730 | break; 731 | case 4: 732 | var value = /** @type {number} */ (reader.readUint32()); 733 | msg.setEncryptiontype(value); 734 | break; 735 | default: 736 | reader.skipField(); 737 | break; 738 | } 739 | } 740 | return msg; 741 | }; 742 | 743 | 744 | /** 745 | * Serializes the message to binary data (in protobuf wire format). 746 | * @return {!Uint8Array} 747 | */ 748 | proto.protobuf.EncryptedPayload.prototype.serializeBinary = function() { 749 | var writer = new jspb.BinaryWriter(); 750 | proto.protobuf.EncryptedPayload.serializeBinaryToWriter(this, writer); 751 | return writer.getResultBuffer(); 752 | }; 753 | 754 | 755 | /** 756 | * Serializes the given message to binary data (in protobuf wire 757 | * format), writing to the given BinaryWriter. 758 | * @param {!proto.protobuf.EncryptedPayload} message 759 | * @param {!jspb.BinaryWriter} writer 760 | * @suppress {unusedLocalVariables} f is only used for nested messages 761 | */ 762 | proto.protobuf.EncryptedPayload.serializeBinaryToWriter = function(message, writer) { 763 | var f = undefined; 764 | f = message.getSender(); 765 | if (f !== 0) { 766 | writer.writeUint32( 767 | 1, 768 | f 769 | ); 770 | } 771 | f = message.getReceiversList(); 772 | if (f.length > 0) { 773 | writer.writeRepeatedMessage( 774 | 2, 775 | f, 776 | proto.protobuf.Receiver.serializeBinaryToWriter 777 | ); 778 | } 779 | f = message.getPayload_asU8(); 780 | if (f.length > 0) { 781 | writer.writeBytes( 782 | 3, 783 | f 784 | ); 785 | } 786 | f = message.getEncryptiontype(); 787 | if (f !== 0) { 788 | writer.writeUint32( 789 | 4, 790 | f 791 | ); 792 | } 793 | }; 794 | 795 | 796 | /** 797 | * optional uint32 Sender = 1; 798 | * @return {number} 799 | */ 800 | proto.protobuf.EncryptedPayload.prototype.getSender = function() { 801 | return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); 802 | }; 803 | 804 | 805 | /** 806 | * @param {number} value 807 | * @return {!proto.protobuf.EncryptedPayload} returns this 808 | */ 809 | proto.protobuf.EncryptedPayload.prototype.setSender = function(value) { 810 | return jspb.Message.setProto3IntField(this, 1, value); 811 | }; 812 | 813 | 814 | /** 815 | * repeated Receiver Receivers = 2; 816 | * @return {!Array} 817 | */ 818 | proto.protobuf.EncryptedPayload.prototype.getReceiversList = function() { 819 | return /** @type{!Array} */ ( 820 | jspb.Message.getRepeatedWrapperField(this, proto.protobuf.Receiver, 2)); 821 | }; 822 | 823 | 824 | /** 825 | * @param {!Array} value 826 | * @return {!proto.protobuf.EncryptedPayload} returns this 827 | */ 828 | proto.protobuf.EncryptedPayload.prototype.setReceiversList = function(value) { 829 | return jspb.Message.setRepeatedWrapperField(this, 2, value); 830 | }; 831 | 832 | 833 | /** 834 | * @param {!proto.protobuf.Receiver=} opt_value 835 | * @param {number=} opt_index 836 | * @return {!proto.protobuf.Receiver} 837 | */ 838 | proto.protobuf.EncryptedPayload.prototype.addReceivers = function(opt_value, opt_index) { 839 | return jspb.Message.addToRepeatedWrapperField(this, 2, opt_value, proto.protobuf.Receiver, opt_index); 840 | }; 841 | 842 | 843 | /** 844 | * Clears the list making it empty but non-null. 845 | * @return {!proto.protobuf.EncryptedPayload} returns this 846 | */ 847 | proto.protobuf.EncryptedPayload.prototype.clearReceiversList = function() { 848 | return this.setReceiversList([]); 849 | }; 850 | 851 | 852 | /** 853 | * optional bytes Payload = 3; 854 | * @return {!(string|Uint8Array)} 855 | */ 856 | proto.protobuf.EncryptedPayload.prototype.getPayload = function() { 857 | return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 3, "")); 858 | }; 859 | 860 | 861 | /** 862 | * optional bytes Payload = 3; 863 | * This is a type-conversion wrapper around `getPayload()` 864 | * @return {string} 865 | */ 866 | proto.protobuf.EncryptedPayload.prototype.getPayload_asB64 = function() { 867 | return /** @type {string} */ (jspb.Message.bytesAsB64( 868 | this.getPayload())); 869 | }; 870 | 871 | 872 | /** 873 | * optional bytes Payload = 3; 874 | * Note that Uint8Array is not supported on all browsers. 875 | * @see http://caniuse.com/Uint8Array 876 | * This is a type-conversion wrapper around `getPayload()` 877 | * @return {!Uint8Array} 878 | */ 879 | proto.protobuf.EncryptedPayload.prototype.getPayload_asU8 = function() { 880 | return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( 881 | this.getPayload())); 882 | }; 883 | 884 | 885 | /** 886 | * @param {!(string|Uint8Array)} value 887 | * @return {!proto.protobuf.EncryptedPayload} returns this 888 | */ 889 | proto.protobuf.EncryptedPayload.prototype.setPayload = function(value) { 890 | return jspb.Message.setProto3BytesField(this, 3, value); 891 | }; 892 | 893 | 894 | /** 895 | * optional uint32 EncryptionType = 4; 896 | * @return {number} 897 | */ 898 | proto.protobuf.EncryptedPayload.prototype.getEncryptiontype = function() { 899 | return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0)); 900 | }; 901 | 902 | 903 | /** 904 | * @param {number} value 905 | * @return {!proto.protobuf.EncryptedPayload} returns this 906 | */ 907 | proto.protobuf.EncryptedPayload.prototype.setEncryptiontype = function(value) { 908 | return jspb.Message.setProto3IntField(this, 4, value); 909 | }; 910 | 911 | 912 | 913 | 914 | 915 | if (jspb.Message.GENERATE_TO_OBJECT) { 916 | /** 917 | * Creates an object representation of this proto. 918 | * Field names that are reserved in JavaScript and will be renamed to pb_name. 919 | * Optional fields that are not set will be set to undefined. 920 | * To access a reserved field use, foo.pb_, eg, foo.pb_default. 921 | * For the list of reserved names please see: 922 | * net/proto2/compiler/js/internal/generator.cc#kKeyword. 923 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the 924 | * JSPB instance for transitional soy proto support: 925 | * http://goto/soy-param-migration 926 | * @return {!Object} 927 | */ 928 | proto.protobuf.Receiver.prototype.toObject = function(opt_includeInstance) { 929 | return proto.protobuf.Receiver.toObject(opt_includeInstance, this); 930 | }; 931 | 932 | 933 | /** 934 | * Static version of the {@see toObject} method. 935 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include 936 | * the JSPB instance for transitional soy proto support: 937 | * http://goto/soy-param-migration 938 | * @param {!proto.protobuf.Receiver} msg The msg instance to transform. 939 | * @return {!Object} 940 | * @suppress {unusedLocalVariables} f is only used for nested messages 941 | */ 942 | proto.protobuf.Receiver.toObject = function(includeInstance, msg) { 943 | var f, obj = { 944 | index: jspb.Message.getFieldWithDefault(msg, 1, 0), 945 | encryptedkey: msg.getEncryptedkey_asB64() 946 | }; 947 | 948 | if (includeInstance) { 949 | obj.$jspbMessageInstance = msg; 950 | } 951 | return obj; 952 | }; 953 | } 954 | 955 | 956 | /** 957 | * Deserializes binary data (in protobuf wire format). 958 | * @param {jspb.ByteSource} bytes The bytes to deserialize. 959 | * @return {!proto.protobuf.Receiver} 960 | */ 961 | proto.protobuf.Receiver.deserializeBinary = function(bytes) { 962 | var reader = new jspb.BinaryReader(bytes); 963 | var msg = new proto.protobuf.Receiver; 964 | return proto.protobuf.Receiver.deserializeBinaryFromReader(msg, reader); 965 | }; 966 | 967 | 968 | /** 969 | * Deserializes binary data (in protobuf wire format) from the 970 | * given reader into the given message object. 971 | * @param {!proto.protobuf.Receiver} msg The message object to deserialize into. 972 | * @param {!jspb.BinaryReader} reader The BinaryReader to use. 973 | * @return {!proto.protobuf.Receiver} 974 | */ 975 | proto.protobuf.Receiver.deserializeBinaryFromReader = function(msg, reader) { 976 | while (reader.nextField()) { 977 | if (reader.isEndGroup()) { 978 | break; 979 | } 980 | var field = reader.getFieldNumber(); 981 | switch (field) { 982 | case 1: 983 | var value = /** @type {number} */ (reader.readUint32()); 984 | msg.setIndex(value); 985 | break; 986 | case 2: 987 | var value = /** @type {!Uint8Array} */ (reader.readBytes()); 988 | msg.setEncryptedkey(value); 989 | break; 990 | default: 991 | reader.skipField(); 992 | break; 993 | } 994 | } 995 | return msg; 996 | }; 997 | 998 | 999 | /** 1000 | * Serializes the message to binary data (in protobuf wire format). 1001 | * @return {!Uint8Array} 1002 | */ 1003 | proto.protobuf.Receiver.prototype.serializeBinary = function() { 1004 | var writer = new jspb.BinaryWriter(); 1005 | proto.protobuf.Receiver.serializeBinaryToWriter(this, writer); 1006 | return writer.getResultBuffer(); 1007 | }; 1008 | 1009 | 1010 | /** 1011 | * Serializes the given message to binary data (in protobuf wire 1012 | * format), writing to the given BinaryWriter. 1013 | * @param {!proto.protobuf.Receiver} message 1014 | * @param {!jspb.BinaryWriter} writer 1015 | * @suppress {unusedLocalVariables} f is only used for nested messages 1016 | */ 1017 | proto.protobuf.Receiver.serializeBinaryToWriter = function(message, writer) { 1018 | var f = undefined; 1019 | f = message.getIndex(); 1020 | if (f !== 0) { 1021 | writer.writeUint32( 1022 | 1, 1023 | f 1024 | ); 1025 | } 1026 | f = message.getEncryptedkey_asU8(); 1027 | if (f.length > 0) { 1028 | writer.writeBytes( 1029 | 2, 1030 | f 1031 | ); 1032 | } 1033 | }; 1034 | 1035 | 1036 | /** 1037 | * optional uint32 Index = 1; 1038 | * @return {number} 1039 | */ 1040 | proto.protobuf.Receiver.prototype.getIndex = function() { 1041 | return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); 1042 | }; 1043 | 1044 | 1045 | /** 1046 | * @param {number} value 1047 | * @return {!proto.protobuf.Receiver} returns this 1048 | */ 1049 | proto.protobuf.Receiver.prototype.setIndex = function(value) { 1050 | return jspb.Message.setProto3IntField(this, 1, value); 1051 | }; 1052 | 1053 | 1054 | /** 1055 | * optional bytes EncryptedKey = 2; 1056 | * @return {!(string|Uint8Array)} 1057 | */ 1058 | proto.protobuf.Receiver.prototype.getEncryptedkey = function() { 1059 | return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 2, "")); 1060 | }; 1061 | 1062 | 1063 | /** 1064 | * optional bytes EncryptedKey = 2; 1065 | * This is a type-conversion wrapper around `getEncryptedkey()` 1066 | * @return {string} 1067 | */ 1068 | proto.protobuf.Receiver.prototype.getEncryptedkey_asB64 = function() { 1069 | return /** @type {string} */ (jspb.Message.bytesAsB64( 1070 | this.getEncryptedkey())); 1071 | }; 1072 | 1073 | 1074 | /** 1075 | * optional bytes EncryptedKey = 2; 1076 | * Note that Uint8Array is not supported on all browsers. 1077 | * @see http://caniuse.com/Uint8Array 1078 | * This is a type-conversion wrapper around `getEncryptedkey()` 1079 | * @return {!Uint8Array} 1080 | */ 1081 | proto.protobuf.Receiver.prototype.getEncryptedkey_asU8 = function() { 1082 | return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( 1083 | this.getEncryptedkey())); 1084 | }; 1085 | 1086 | 1087 | /** 1088 | * @param {!(string|Uint8Array)} value 1089 | * @return {!proto.protobuf.Receiver} returns this 1090 | */ 1091 | proto.protobuf.Receiver.prototype.setEncryptedkey = function(value) { 1092 | return jspb.Message.setProto3BytesField(this, 2, value); 1093 | }; 1094 | 1095 | 1096 | --------------------------------------------------------------------------------