TICKET

Правила розыгрыша

Что это

SVOJ — маркет хендмейда в Белграде: 40 мастеров, один день, всё сделано руками.

Маркет проходит 29 августа. В этот же день среди покупателей разыгрываются билеты на концерт СБПЧ.

Как получить SVOJ TICKET

Купи что-нибудь у мастера на сумму от 1.000 RSD — и получишь SVOJ TICKET: бумажный билет с номером и кодом.

От одного мастера — только один билет. Но мастеров 40, так что билетов может быть много, и каждый участвует в розыгрыше отдельно: чем больше билетов, тем выше шансы.

Билет играет, только если зарегистрировать его на этом сайте до 20:00 29 августа. Незарегистрированный билет в розыгрыш не попадает.

Как участвовать

Зарегистрируй билет на этом сайте до 20:00 29.08 — наведи камеру на QR с оборота или введи номер и код вручную на главной. Незарегистрированный билет в розыгрыше не участвует, даже если он у тебя на руках.

Билетов можно зарегистрировать сколько угодно — по одному от каждого мастера. Каждый участвует отдельно и повышает твои шансы.

Приз

Три победителя. Каждый получает билет на концерт СБПЧ.

Приз не выдаётся деньгами и не обменивается на денежный эквивалент.

Бумажный билет для получения приза не нужен. SVOJ TICKET — одноразовый: он нужен ровно один раз, чтобы зарегистрироваться на сайте. Дальше всё привязано к твоей регистрации, и мы свяжемся по тому контакту, который ты оставил. Потерял бумажку после регистрации — ничего страшного.

3.12 Zappa Barkа

Кто не участвует

В розыгрыше не участвуют мастера маркета, организаторы и их близкие родственники.

Билет не продаётся и не передаётся другому человеку: приз получает тот, кто оставил контакт при регистрации.

Итоги

Розыгрыш вечером 29.08. Победители появятся на главной странице сайта и в инстаграме @svoj.market. Мы сами напишем победителям в Instagram или Telegram — по контакту из регистрации.

Как устроен розыгрыш

Ниже — что именно мы делаем, в каком порядке и почему результат нельзя подменить незаметно. Проверить может любой, никаких особых знаний не нужно: достаточно бумажного билета и умения открыть сайт.

Порядок действий

  1. До маркета. Мы сгенерировали 32 случайных байта — назовём это ключом. Посчитали от него SHA-256 (это функция, которая превращает любые данные в строку из 64 знаков) и опубликовали только результат: он напечатан на каждом из билетов и выложен в инстаграм. Сам ключ до розыгрыша не показывали никому.
  2. 29.08 до 20:00. Люди регистрируют билеты. Список номеров открыт и виден всем в реальном времени.
  3. После 20:00. Регистрация закрывается автоматически. Список фиксируется целиком и публикуется. С этого момента в него нельзя ни добавить номер, ни убрать.
  4. Затем публикуется сам ключ. Любой может посчитать от него SHA-256 и сравнить со строкой на своём билете.
  5. Победители вычисляются по формуле из ключа и списка. Формула ниже, результат у всех получается один и тот же.

Формула

Три победителя, для каждого места считается отдельный хэш. Выпавший билет убирается, чтобы один номер не занял два места.

номера  = отсортированные номера зарегистрированных билетов
payload = ключ + "|" + внешняя_энтропия + "|" + номера.join(",")

для места = 1, 2, 3:
    digest = sha256(payload + "|" + место)
    индекс = первые 16 знаков digest как число, остаток от деления на длину списка
    победитель = номера[индекс], затем номер убирается из списка

Почему подмена не пройдёт

Всё держится на двух свойствах SHA-256, и оба проверяемы независимо от нас:

Отсюда три следствия:

  1. Ключ нельзя подогнать под нужного победителя. Его отпечаток напечатан на тираже за несколько дней до маркета — тогда список участников ещё не существовал, и вычислить по нему победителя было не из чего.
  2. Список нельзя подогнать под ключ. На момент публикации списка ключ не был известен никому, кроме организатора, а сам список к этому моменту уже у всех перед глазами и зафиксирован.
  3. Нельзя объявить не тот номер. Формула и все исходные данные публичны: расхождение обнаружит любой, кто повторит расчёт.

Чего эта схема не гарантирует

Честнее сказать сразу, где её границы.

Как проверить самому

  1. Возьми свой билет и посмотри строку под номером — это отпечаток ключа.
  2. После розыгрыша открой страницу проверки. Она считает всё в твоём браузере: после загрузки можно отключить интернет, расчёт всё равно пройдёт.
  3. Не доверяешь странице — вставь туда свою копию списка, сохранённую до розыгрыша. Расчёт пойдёт по твоим данным.
  4. Не доверяешь и этому — пересчитай сам. Полный код на Python:
import hashlib

key = "…"     # ключ, опубликованный после розыгрыша
entropy = "…" # внешняя энтропия (может быть пустой строкой)
nums = ["1234", "5678"]  # опубликованный список номеров

# 1. Совпадает ли отпечаток с тем, что на билете
print(hashlib.sha256(key.encode()).hexdigest())

# 2. Кто победил
nums = sorted(nums, key=int)
payload = key + "|" + entropy + "|" + ",".join(nums)
pool = list(nums)
for place in (1, 2, 3):
    d = hashlib.sha256((payload + "|" + str(place)).encode()).hexdigest()
    print(place, pool.pop(int(d[:16], 16) % len(pool)))

Первая строка должна совпасть с отпечатком на твоём билете. Совпала — значит ключ тот самый, и всё остальное уже арифметика.

Что сохранить, если хочешь проверить позже

Этих трёх вещей хватит, чтобы перепроверить результат когда угодно, даже если сайт перестанет работать.

Источники

Схема называется commitment scheme — схема обязательства. Это не наше изобретение, ей несколько десятков лет:

Контакты

Вопросы — в директ Instagram @svoj.market.

Если билет не регистрируется, не выбрасывай его: напиши нам и назови номер и код, разберёмся вручную.

Draw rules

What this is

SVOJ is a handmade market in Belgrade: 40 makers, one day, everything made by hand.

The market takes place on 29 August. On the same day we draw tickets to the SBPCH concert among the shoppers.

How to get a SVOJ TICKET

Buy something from a maker for 1,000 RSD or more and you get a SVOJ TICKET: a paper ticket with a number and a code.

One ticket per maker. But there are 45 makers, so you can collect several — and each one enters the draw separately: the more tickets, the better your chances.

A ticket only counts if you register it on this site before 20:00 on 29 August. An unregistered ticket does not enter the draw.

How to enter

Register your ticket on this site before 20:00 on 29.08 — via the QR code on the back, or by hand on the home page. An unregistered ticket does not enter the draw.

You may register as many tickets as you have — one from each maker. Each one enters separately.

Prize

Three winners. Each gets a ticket to the SBPCH concert.

The prize is not paid in cash and cannot be exchanged for money.

You do not need the paper ticket to claim the prize. A SVOJ TICKET is single-use: it is needed exactly once, to register on the site. After that everything is tied to your registration and we contact you using the details you left. Lost the slip after registering? No problem.

3.12 Zappa Barka

Who cannot enter

Makers, organisers and their close relatives do not take part in the draw.

Tickets are not for sale and cannot be passed on: the prize goes to the person whose contact was left at registration.

Results

The draw takes place on the evening of 29.08. Results are posted on Instagram @svoj.market and on this site.

How the draw works

Below is exactly what we do, in what order, and why the result cannot be swapped unnoticed. Anyone can check it — no special knowledge needed, just your paper ticket and a browser.

The order of steps

  1. Before the market. We generated 32 random bytes — call it the key. We computed its SHA-256 (a function that turns any data into a 64-character string) and published only the result: it is printed on every ticket and posted on Instagram. The key itself was shown to nobody.
  2. 29.08, until 20:00. People register their tickets. The list of numbers is public and updates live.
  3. After 20:00. Registration closes automatically. The list is frozen whole and published. From that moment nothing can be added or removed.
  4. Then the key itself is published. Anyone can compute its SHA-256 and compare it with the string printed on their ticket.
  5. The winners are computed from the key and the list by the formula below. Everyone who repeats it gets the same answer.

The formula

Three winners; each place gets its own hash. A drawn ticket is removed so that one number cannot take two places.

nums    = sorted numbers of registered tickets
payload = key + "|" + external_entropy + "|" + nums.join(",")

for place in 1, 2, 3:
    digest = sha256(payload + "|" + place)
    index = first 16 chars of digest as an integer, modulo list length
    winner = nums[index], then that number is removed

Why substitution does not work

Everything rests on two properties of SHA-256, both verifiable independently of us:

Three consequences:

  1. The key cannot be tuned to a chosen winner. Its fingerprint was printed on the run days before the market, when the entry list did not yet exist.
  2. The list cannot be tuned to the key. When the list was published, nobody outside the organiser knew the key — and by then the list was already public and frozen.
  3. A different number cannot be announced. The formula and all inputs are public: anyone repeating the computation would spot the discrepancy.

What this scheme does not guarantee

It is fairer to state the limits outright.

How to check it yourself

  1. Take your ticket and look at the line under the number — that is the fingerprint of the key.
  2. After the draw, open the verification page. It computes everything in your own browser: once loaded, you can go offline and it still works.
  3. Do not trust the page? Paste in your own copy of the list, saved before the draw. The maths will use yours.
  4. Do not trust that either? Redo it yourself. Full Python code:
import hashlib

key = "…"     # the key published after the draw
entropy = "…" # external entropy (may be an empty string)
nums = ["1234", "5678"]  # the published list of numbers

# 1. Does the fingerprint match the one on the ticket
print(hashlib.sha256(key.encode()).hexdigest())

# 2. Who won
nums = sorted(nums, key=int)
payload = key + "|" + entropy + "|" + ",".join(nums)
pool = list(nums)
for place in (1, 2, 3):
    d = hashlib.sha256((payload + "|" + str(place)).encode()).hexdigest()
    print(place, pool.pop(int(d[:16], 16) % len(pool)))

The first line must match the fingerprint on your ticket. If it does, the key is the committed one and the rest is arithmetic.

What to keep if you want to check later

Sources

The scheme is called a commitment scheme. We did not invent it; it has been around for decades:

Contact

Questions — Instagram direct message to @svoj.market.

If your ticket will not register, do not throw it away: message us with the number and the code and we will sort it out by hand.