Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAM handling layer #119

Merged
merged 16 commits into from
Sep 23, 2019
Merged
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@
*.dylib
*.test
*.out
.experimental/
.experimental/
examples/mam-transmit/transmit.sh
examples/mam-receive/receive.sh
62 changes: 62 additions & 0 deletions examples/mam-receive/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package main

import (
"flag"
"fmt"
"log"
"time"

"github.com/simia-tech/env"

"github.com/iotaledger/iota.go/api"
"github.com/iotaledger/iota.go/mam/v1"
)

var (
endpointURL = env.String("ENDPOINT_URL", "https://nodes.thetangle.org:443")
mode = env.String("MODE", "public", env.AllowedValues("public", "private", "restricted"))
sideKey = env.String("SIDE_KEY", "")
)

func main() {
follow := flag.Bool("f", false, "don't exit and check every second for new messages")
flag.Parse()
root := flag.Arg(0)

cm, err := mam.ParseChannelMode(mode.Get())
if err != nil {
log.Fatal(err)
}

api, err := api.ComposeAPI(api.HTTPClientSettings{
URI: endpointURL.Get(),
})
if err != nil {
log.Fatal(err)
}

receiver := mam.NewReceiver(api)
if err := receiver.SetMode(cm, sideKey.Get()); err != nil {
log.Fatal(err)
}

fmt.Printf("receive root %q from %s channel...\n", root, cm)
loop:
nextRoot, messages, err := receiver.Receive(root)
if err != nil {
log.Fatal(err)
}
for _, message := range messages {
fmt.Println(message)
}
if *follow {
time.Sleep(time.Second)
if len(messages) > 0 {
root = nextRoot
}
goto loop
}
if len(messages) == 0 {
fmt.Println("no messages found")
}
}
56 changes: 56 additions & 0 deletions examples/mam-transmit/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package main

import (
"flag"
"fmt"
"log"

"github.com/simia-tech/env"

"github.com/iotaledger/iota.go/api"
"github.com/iotaledger/iota.go/consts"
"github.com/iotaledger/iota.go/mam/v1"
"github.com/iotaledger/iota.go/pow"
)

var (
endpointURL = env.String("ENDPOINT_URL", "https://nodes.thetangle.org:443")
seed = env.String("SEED", "")
mwm = env.Int("MWM", 9)
mode = env.String("MODE", "public", env.AllowedValues("public", "private", "restricted"))
sideKey = env.String("SIDE_KEY", "")
)

func main() {
flag.Parse()
messages := flag.Args()

cm, err := mam.ParseChannelMode(mode.Get())
if err != nil {
log.Fatal(err)
}

_, powFunc := pow.GetFastestProofOfWorkImpl()

api, err := api.ComposeAPI(api.HTTPClientSettings{
URI: endpointURL.Get(),
LocalProofOfWorkFunc: powFunc,
})
if err != nil {
log.Fatal(err)
}

transmitter := mam.NewTransmitter(api, seed.Get(), uint64(mwm.Get()), consts.SecurityLevelMedium)
if err := transmitter.SetMode(cm, sideKey.Get()); err != nil {
log.Fatal(err)
}

for _, message := range messages {
fmt.Printf("transmit message %q to %s channel...\n", message, cm)
root, err := transmitter.Transmit(message)
if err != nil {
log.Fatal(err)
}
fmt.Printf("transmitted to root %q\n", root)
}
}
7 changes: 5 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,24 @@ go 1.12

require (
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9 // indirect
github.com/apsdehal/go-logger v0.0.0-20190506062552-f85330a4b532 // indirect
github.com/beevik/ntp v0.2.0
github.com/cespare/xxhash v1.1.0
github.com/dgraph-io/badger v1.5.4
github.com/dgryski/go-farm v0.0.0-20190323231341-8198c7b169ec // indirect
github.com/go-stack/stack v1.8.0 // indirect
github.com/golang/snappy v0.0.1 // indirect
github.com/google/go-cmp v0.2.0 // indirect
github.com/onsi/ginkgo v1.8.0
github.com/onsi/gomega v1.5.0
github.com/pkg/errors v0.8.1
github.com/simia-tech/env v0.1.0
github.com/stretchr/testify v1.3.0 // indirect
github.com/tidwall/pretty v1.0.0 // indirect
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c // indirect
github.com/xdg/stringprep v1.0.0 // indirect
go.mongodb.org/mongo-driver v1.0.0
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5 // indirect
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 // indirect
golang.org/x/net v0.0.0-20190311183353-d8887717615a // indirect
golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect
gopkg.in/h2non/gock.v1 v1.0.14
)
21 changes: 17 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,28 @@ github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9 h1:HD8gA2tkBy
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/apsdehal/go-logger v0.0.0-20190506062552-f85330a4b532 h1:xTYdKP4GbVSANiKn8bdlBzQp08Nq8I1wlB49Dunh0QA=
github.com/apsdehal/go-logger v0.0.0-20190506062552-f85330a4b532/go.mod h1:U3/8D6R9+bVpX0ORZjV+3mU9pQ86m7h1lESgJbXNvXA=
github.com/beevik/ntp v0.2.0 h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw=
github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgraph-io/badger v1.5.4 h1:gVTrpUTbbr/T24uvoCaqY2KSHfNLVGm0w+hbee2HMeg=
github.com/dgraph-io/badger v1.5.4/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ=
github.com/dgryski/go-farm v0.0.0-20190323231341-8198c7b169ec h1:sElGDs3V8VdCxH5tWi0ycWJzteOPLJ3HtItSSKI95PY=
github.com/dgryski/go-farm v0.0.0-20190323231341-8198c7b169ec/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
Expand All @@ -36,29 +39,39 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/simia-tech/env v0.1.0 h1:QTq3uAvWT0HUMgH6VWQmOOdb81tjizFKNmaQNOuPu90=
github.com/simia-tech/env v0.1.0/go.mod h1:eVRQ7W5NXXHifpPAcTJ3r5EmoGgMn++dXfSVbZv3Opo=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0=
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
go.mongodb.org/mongo-driver v1.0.0 h1:KxPRDyfB2xXnDE2My8acoOWBQkfv3tz0SaWTRZjJR0c=
go.mongodb.org/mongo-driver v1.0.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5 h1:bselrhR0Or1vomJZC8ZIjWtbDmn9OYFLX5Ik9alpJpE=
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e h1:nFYrTHrdrAOpShe27kaFHjsqYSEQ0KWqdWLu3xuZJts=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
Expand Down
47 changes: 47 additions & 0 deletions mam/v1/address.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package mam

import (
"github.com/iotaledger/iota.go/address"
"github.com/iotaledger/iota.go/consts"
"github.com/iotaledger/iota.go/curl"
"github.com/iotaledger/iota.go/trinary"
)

func makeAddress(mode ChannelMode, root trinary.Trits, sideKey trinary.Trytes) (trinary.Trytes, error) {
if mode == ChannelModePublic {
return toAddress(root)
}

sideKeyTrits, err := trinary.TrytesToTrits(sideKey)
if err != nil {
return "", err
}

h := curl.NewCurlP81()
if err := h.Absorb(sideKeyTrits); err != nil {
return "", err
}
if err := h.Absorb(root); err != nil {
return "", err
}
hashedRoot, err := h.Squeeze(consts.HashTrinarySize)
if err != nil {
return "", err
}

return toAddress(hashedRoot)
}

func toAddress(root trinary.Trits) (trinary.Trytes, error) {
rootTrytes, err := trinary.TritsToTrytes(root)
if err != nil {
return "", err
}

chkSum, err := address.Checksum(rootTrytes)
if err != nil {
return "", err
}

return rootTrytes + chkSum, nil
}
15 changes: 15 additions & 0 deletions mam/v1/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package mam

import (
"github.com/iotaledger/iota.go/api"
"github.com/iotaledger/iota.go/bundle"
"github.com/iotaledger/iota.go/transaction"
"github.com/iotaledger/iota.go/trinary"
)

// API defines an interface with a subset of methods of `api.API`.
type API interface {
PrepareTransfers(seed trinary.Trytes, transfers bundle.Transfers, opts api.PrepareTransfersOptions) ([]trinary.Trytes, error)
SendTrytes(trytes []trinary.Trytes, depth uint64, mwm uint64, reference ...trinary.Hash) (bundle.Bundle, error)
FindTransactionObjects(query api.FindTransactionsQuery) (transaction.Transactions, error)
}
56 changes: 56 additions & 0 deletions mam/v1/api_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package mam_test

import (
"github.com/pkg/errors"

"github.com/iotaledger/iota.go/api"
"github.com/iotaledger/iota.go/bundle"
"github.com/iotaledger/iota.go/transaction"
"github.com/iotaledger/iota.go/trinary"
)

type fakeAPI struct {
prepareTransfers func(trinary.Trytes, bundle.Transfers, api.PrepareTransfersOptions) ([]trinary.Trytes, error)
sendTrytes func([]trinary.Trytes, uint64, uint64, ...trinary.Hash) (bundle.Bundle, error)
findTransactionObjects func(api.FindTransactionsQuery) (transaction.Transactions, error)
}

func newFakeAPI() *fakeAPI {
return &fakeAPI{
prepareTransfers: func(_ trinary.Trytes, _ bundle.Transfers, _ api.PrepareTransfersOptions) ([]trinary.Trytes, error) {
return nil, errors.New("not implemented")
},
sendTrytes: func(_ []trinary.Trytes, _ uint64, _ uint64, _ ...trinary.Hash) (bundle.Bundle, error) {
return nil, errors.New("not implemented")
},
findTransactionObjects: func(_ api.FindTransactionsQuery) (transaction.Transactions, error) {
return nil, errors.New("not implemented")
},
}
}

func (f *fakeAPI) PrepareTransfers(seed trinary.Trytes, transfers bundle.Transfers, opts api.PrepareTransfersOptions) ([]trinary.Trytes, error) {
return f.prepareTransfers(seed, transfers, opts)
}

func (f *fakeAPI) SendTrytes(trytes []trinary.Trytes, depth uint64, mwm uint64, reference ...trinary.Hash) (bundle.Bundle, error) {
return f.sendTrytes(trytes, depth, mwm, reference...)
}

func (f *fakeAPI) FindTransactionObjects(query api.FindTransactionsQuery) (transaction.Transactions, error) {
return f.findTransactionObjects(query)
}

func err(returns []interface{}) error {
if len(returns) == 0 {
return nil
}
last := returns[len(returns)-1]
if last == nil {
return nil
}
if e, ok := last.(error); ok {
return e
}
return nil
}
42 changes: 42 additions & 0 deletions mam/v1/channel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package mam

import (
"github.com/iotaledger/iota.go/consts"
"github.com/iotaledger/iota.go/trinary"
)

type channel struct {
mode ChannelMode
sideKey trinary.Trytes
nextRoot trinary.Trits
securityLevel consts.SecurityLevel
start uint64
count uint64
nextCount uint64
index uint64
}

func newChannel(securityLevel consts.SecurityLevel) *channel {
return &channel{
mode: ChannelModePublic,
sideKey: consts.NullHashTrytes,
securityLevel: securityLevel,
start: 0,
count: 1,
nextCount: 1,
index: 0,
}
}

func (c *channel) incIndex() {
if c.index == c.count-1 {
c.start += c.nextCount
c.index = 0
} else {
c.index++
}
}

func (c *channel) nextStart() uint64 {
return c.start + c.count
}
Loading