Skip to content
This repository has been archived by the owner on Aug 2, 2021. It is now read-only.

pss: add trojan chunks #2148

Merged
merged 98 commits into from
Apr 10, 2020
Merged

pss: add trojan chunks #2148

merged 98 commits into from
Apr 10, 2020

Conversation

mortelli
Copy link
Contributor

@mortelli mortelli commented Apr 2, 2020

EXPERIMENTAL
(will not merge to master)


This PR adds implements trojan chunks.

Related issue: #2153

Implementation overview

new package

trojan

new types

  • Topic
    • alias for 32 byte array
  • Message, contains:
    • length (2 byte array)
    • topic (of the Topic type)
    • payload and padding (both of them byte slices)

main new functions

  • NewTopic helper function constructs a Topic by hashing an input string
  • newMessage creates a Message based on the given Topic plus a payload (byte slice)
    • this function also determines the length and padding fields based on the given params
  • Wrap function takes targets (slice of byte slices) plus a Message type, and returns a chunk.Chunk. this function is in charge of:
    • calling a func to check that targets are valid
    • calling a func to create a new span
    • calling a func to iterate a nonce so that when it is hashed along with the span and serialized Message, the resulting hash has a prefix which matches one of the targets
      • this iterator func will return a new Chunk with the matching hash set as its address, plus the aforementioned serialized fields set as its payload

Open questions

  1. is it OK to call crypto.Keccack256Hash to hash a string to create a topic, or must we use crypto.Keccack256?
    please use the exact same hash as used everywhere else. no new variant to be introduced here.
  2. is it OK to have a Messageg var as a param for the Wrap func, rather than a byte slice (payload)? if a payload were received, this would mean that param is the serialization of the trojan message, which would then have to be de-serialized to find a nonce
    perfectly. ok imho
  3. should the span field be encoded in little-endian or big-endian?
    let's try to be consistent with other parts of the codebase. so i guess little?
    done
  4. why do we need to call Reset on a storage.SwarmHash var?
    you do not need to call it if it is freshly created hasher
  5. since we don't have a trojan chunk struct, we are relying on the helper func serializeTrojanChunk to serialize the trojan chunk fields (rather than a binary marshaller). don't we need a deserializeTrojanChunk func too? this should be used on the receiving node to figure out whether the received chunk payload contains a serialized trojanMsg serializeTrojanChunk function now removed as it was unnecessary
  6. should Message's UnmarshalBinary function also:
    6.1 check if the received byte slice is longer than 4064 bytes? (and return an error if so)
    6.2 ignore any bytes in the slice past byte #4064?
    6.3 check that for decoded length l, it follows that 0 ≤ l ≤ 4030?

    none of them needed, whenever deserialise, you get the data from a chunk which is itself validated for payload length, in fact all restrictions enforced here just enforce the restrictions on content addressed chunks

TODOs

  1. make this work with storage.BMTHash rather than storage.SHA3Hash (currently, BMT hash does not change with each iteration loop; not sure why)
  2. encrypt the trojan message when forming the trojan chunk (currently just serializes it) — maybe not for the current implementation
  3. prevent an infinite loop in the trojan chunk iteration (how?). the given addresses could be too long to find a nonce in a reasonable time
  4. test that if the random nonce overflows, the iteration still works
  5. add failure tests

@mortelli mortelli added in progress global pinning experimental implementation of global pinning labels Apr 2, 2020
@mortelli mortelli requested review from zelig and santicomp2014 April 2, 2020 23:37
@mortelli mortelli self-assigned this Apr 2, 2020
Copy link
Contributor

@santicomp2014 santicomp2014 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There a couple of minor things I left, I think this I really good implementation.
Awesome job.

// Wrap creates a new trojan chunk for the given targets and trojan message
// a trojan chunk is a content-addressed chunk made up of span, a nonce, and a payload
// TODO: discuss if instead of receiving a trojan message, we should receive a byte slice as payload
func (m *Message) Wrap(targets [][]byte) (chunk.Chunk, error) {
Copy link
Contributor

@santicomp2014 santicomp2014 Apr 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

targets [][]byte could be converted into a type ex. type Targets [][]byte
The same argument should be used for Send so exported type would be necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i honestly don't feel strongly either way.

if it's beneficial to us, then yeah, let's add a Targets type. i will keep this in mind when we merge this with the API code

pss/trojan/message.go Outdated Show resolved Hide resolved
pss/trojan/message.go Show resolved Hide resolved
pss/trojan/message_test.go Show resolved Hide resolved
pss/trojan/message_test.go Show resolved Hide resolved

payload := c.Data()
payloadSize := len(payload)
expectedSize := chunk.DefaultSize + 8 // payload + span
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Span could be a constant so it's parametrized in all references

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're starting to convince me...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

open to more opinions

t.Fatalf("trojan chunk payload has an unexpected size of %d rather than %d", payloadSize, expectedSize)
}

span := binary.BigEndian.Uint64(payload[:8])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here with span

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed in previous messages

pss/trojan/message_test.go Outdated Show resolved Hide resolved
Copy link
Contributor

@santicomp2014 santicomp2014 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes I described are not critical, they can be address if needed later.
LGTM

Copy link
Member

@zelig zelig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

really just a few minor things
already approved
also https://travis-ci.org/github/ethersphere/swarm/jobs/672786246#L489
linter indicates another solution

pss/trojan/message.go Outdated Show resolved Hide resolved
pss/trojan/message.go Outdated Show resolved Hide resolved
pss/trojan/message.go Outdated Show resolved Hide resolved
pss/trojan/message.go Outdated Show resolved Hide resolved
}

// toChunk finds a nonce so that when the given trojan chunk fields are hashed, the result will fall in the neighbourhood of one of the given targets
// this is done by iterating the BMT hash of the serialization of the trojan chunk fields until the desired nonce is found
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is done by iteratively enumerating different nonces until the BMT hash of the serialization of the trojan chunk fields results in chunk address that has one of the targets as its prefix

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

pss/trojan/message.go Outdated Show resolved Hide resolved
@zelig zelig marked this pull request as ready for review April 9, 2020 05:15
@mortelli
Copy link
Contributor Author

mortelli commented Apr 9, 2020

really just a few minor things
already approved
also https://travis-ci.org/github/ethersphere/swarm/jobs/672786246#L489
linter indicates another solution

thank you @zelig for the relentless reviewing ❤️

fixed the linter issues as well.

just have a couple of very minor issues that i'd like to resolve before merging and we're good to go

Copy link
Member

@zelig zelig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<3

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
global pinning experimental implementation of global pinning ready for review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants